Search Unity

Moving rigidbodies in FixedUpdate gives less FPS than Update??

Discussion in 'Physics' started by Daragorn, Dec 8, 2018.

  1. Daragorn

    Daragorn

    Joined:
    Feb 24, 2014
    Posts:
    34
    I've been trying to do some stress tests to see how many rigidbodies moving simultaneously and colliding before having FPS issues.
    The weird things i have noticed is that, if i do the random movements in update i get way more fps than doing the same movements in the fixedupdate (which, as suggested by the manual, should be the method in which you move rigidbodies).

    With 1800 rigidbodies, doing this simple loop:
    for (int i = 0; i < rbs.Length; i++)
    {
    rbs.position=new Vector3(Random.Range(0, maxX), 0, Random.Range(0, maxZ));
    }

    I get 20ish FPS if i do it in the Update() and 3fps if i do it in the FixedUpdate() (i also tried using rb.movePosition() to determine the random position, and the results are the same)

    I have also noticed that i get less fps when moving high numbers of static colliders (ie gameobjects with a collider but no rigidbody) vs moving kinematic rigidbodies and, also here, the manual suggest to apply a kinematic rigidbody to objects you want to move to have better performance.....but, even in that case, that's not what i am seeing happening.

    Does anyone has a clue why moving rigidbodies in the update loop is actually better fps-wise than moving them in the fixedupdate where they should supposed to be moving?
     
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    Update happens in the visual update loop. Frames may be skipped if there's too much load here.

    FixedUpdate happens at the physics rate and no frames are skipped here. This means that the content of FixedUpdate will be executed 50 times per second every second, no matter if the work load can be executed in 1/50 sec of not. Thus, an excessive work load here will slow down the entire application timing (Time.time will advance at less than 1 second per second). Visual frames (Update) will be rendered in the few chances available.

    On the other hand, moving rigidbodies within Update doesn't make sense because the physics simulation happens after each FixedUpdate. Thus, you may end applying a lot of values in Update, but only one will be applied - the value that is present when FixedUpdate executes.

    What seems to be happening in your tests is that moving the rigidbodies in Update doesn't have effect, and also frames are skipped if needed, so no significant slowdowns. Physics will take whatever value is in the rigidbody when the physics loop executes (FixedUpdate). This includes repeated values, if two FixedUpdate cycles happen consecutively because Update frames have been skipped. However, moving them in FixedUpdate actually makes the physics to process all them, and it must be done every single FixedUpdate cycle with no frame skipping, at 50 cycles per second. This causes the slow downs in the visual cycle (Update).

    That information is outdated. It was like that before Unity 5, but since Unity 5 you may move static colliders without any penalty.
     
  3. Daragorn

    Daragorn

    Joined:
    Feb 24, 2014
    Posts:
    34
    Thanks for your answer (ahh finally someone could explain me the reason why static collider are less cpu heavy than kinematic rigidbodies....every time i tried to ask this, i always got the response that attaching a kinematic rigidbody should work better...).

    I know the difference between FixedUpdate and Update and, actually that's the reason why i don't get why it is more performing moving them in the Update instead.
    Even if your assumptions were correct and the physics is just taking whatever valuse is in the rigidbody when the next fixedUpdate step happens, it still is strange that it is more performing than doing it in the loop where it should be supposed to be happening.
    It looks like, by moving them in the update loop, you are relieving the physic engine from having to also to the move calculations and, instead, it just does the collision detection (since the movement already happened in the update) so, in the end, it better distribute the workload (move in the update, apply physics in the fixed) and gives better performance overall.
    But it is still a weird result and i am surprised there is no one else that ever noticed or reported this before (not that i could find at least).

    Ok...i did some more testing and it seems that the problem is not the physics itself. I tried to do the same stress test just using static colliders and change the transform position.
    If i do the random movement in the update loop, i can get 18k cubes change position at 35fps. If i move them in the fixedupdate loop, i get 5fps...

    Another thing i have never managed to understand, and has been bothering me since years is why i get those low fps when i should still have a lot of cpu power that could be used.
    I mean, with that 18k cube test, i get 35fps but my cpu usage is at 40-45%, gpu usage is at 20% and ram at 50%...so why i am having such low fps? There should be a ton more computational power to be used
     
  4. Unity (and the Physx engine which used for Unity) is just partially multi-threaded. A lot of things only can be done on the main thread. Which is only one thread, so it uses only one core on your CPU.
    The % what you're seeing in the CPU usage is your entire CPU, all of its threads. When all of the threads are used fully, you will get 100%. But since not everything is can be done in multiple threads, sometimes the main thread is almost fully used, but the other threads are empty.
    This is why you see more power than it is used. Unity is steadily working on multi-threading, and they already have very good results and in the future it will be even more good.
     
  5. SparrowGS

    SparrowGS

    Joined:
    Apr 6, 2017
    Posts:
    2,536
    If you havent already, turn off "auto sync transform" in the project physics settings
     
  6. Daragorn

    Daragorn

    Joined:
    Feb 24, 2014
    Posts:
    34
    Thank, but i already tried that too and it makes no difference (or at least i have never been able to notice it)
     
  7. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    Moving the rigidbodies in Update does nothing in the physics side. Put it simple, the new values are just stored in the data fields of the rigidbodies overriding the existing ones. There's no collision detection nor workload distribution at all. When the physics update happens (FixedUpdate) then the physics engine computes a physics step with whatever values are found in the physic entities at that time.

    Physics runs at 50 fps, but your movement code runs at 35 fps in Update. This means that there are many physic frames where rigidbodies (and colliders, and any physical entity) are not moved at all because they have received no new positions. Physics just continues simulating the physic world without applying new information, which is also an optimization.

    This also means that issuing all those movement commands in Update takes 1/35 seconds. Your display is probably running at 60 fps, so many frames are skipped here for handling that workload.

    However, if you move the code to FixedUpdate, you are forcing a task that requires 1/35 seconds to be executed 50 times per second. No frames are skipped here. Physics is severely slowed down, as computing 1 second of physics now takes 1/35 * 50 = 1.43 seconds. As result, everything slows down and massive frame skipping occurs in Update because the FixedUpdate code is taking nearly all the available CPU time.
     
    Last edited: Dec 9, 2018
    io-games likes this.