Search Unity

Question Rigidbody.Velocity

Discussion in 'Physics' started by shuskry, May 10, 2023.

  1. shuskry

    shuskry

    Joined:
    Oct 10, 2015
    Posts:
    462
    Hello everybody :)

    I've been using: "Rigidbody.Velocity = moveVector * time.FixedDeltatime" for some time

    Until now I put it in the "FixedUpdate" method because it's related to physics.
    But I recently learned that in some cases, where we applied a force at a given point, and not over time, we had to call it in "Update" when the action is call.

    Is "Velocity" in this case?
    My player cannot move at several speeds, either he walks, or he stops, and if I do only once: "Rigidbody.Velocity = moveVector"

    The player moves until I stop it by setting the velocity to zero

    Is the need to put it in a function such as FixedUpdate to be able to control this speed to be the same on all devices with Time.FixedeltaTime? Or not ?

    Have a nice day :D
     
  2. Reaktion

    Reaktion

    Joined:
    Nov 8, 2019
    Posts:
    53
    Hi,

    I guess putting it inside Update or FixedUpdate function won't have the same behaviour.
    What do we know :
    - Update function is called every frame, with Time.deltaTime being the interval of seconds from the last frame to the current one
    - FixedUpdate function is called every fixed frame-rate frame : it can be 0 or many per frames, with Time.fixedDeltaTime being the game time between every physics tick.

    fixedDeltaTime is a fixed value, in order to execute Unity physics at a constant rate over time.
    Physics and FixedUpdate will be executed at a constant rate, regarding of your framerate :
    If you're game is running at 2 FPS : Every frame, your game will try to catch up the physics to the framerate, and call several time the physics simulation.
    If you're game is running at a very high frame rate, the physics won't be executed every frame.

    So, with that being said :
    Setting a velocity inside FixedUpdate is not the same as setting it inside Update.
    In your case, if your framerate is much higher than physics fixed time, setting the rigidbody velocity will result in a slower rigidbody in the FixedUpdate function.
    If your framerate is very slow : Update function will be called every frame, and FixedUpdate will be called several time per frame. You're setting the velocity to a fixed value (moveVector * Time.fixedDeltaTime will always return the same value), so once per frame or many times per frame will be the same for you.

    The question you might ask yourself is : do I want my rigidbody to be moving at a frame-dependant speed ?

    If you want your rigidbody to move at a constant rate over time, you might want to calculate the next position regarding of the deltaTime that has passed. This is not depending on physics, so it doesn't use any of the rigidbody features, so this may not be what you want.

    Use physics when you want to apply forces, and let the Unity physics system move your object. If you want to start moving a rigidbody at a constant speed, you should set a velocity to your rigidbody once (applying a force or changing instantly its velocity), with no drag. Then, once you want to stop your rigidbody, slow it down as you want
     
  3. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    First, I recommend you checking this guide on how/when the Unity events are called:

    https://forum.unity.com/threads/a-c...ution-order-of-unity-event-functions.1381647/

    That said, the correct place to put your code is always FixedUpdate, also when you need to apply discrete forces or impulses. This assures the same behavior across platforms and devices.

    Using Update might be necessary to detect the key presses or input events that trigger those forces. But in those cases, once the event is detected, the actual physics effect should be applied in the next FixedUpdate.

    If you want to go one step further, you could use AddForce with ForceMode.VelocityChange instead of modifying the velocity directly. While modifying the velocity is correct, it involves overriding the internal physics calculations. Using AddForce + VelocityChange implies integrating the requested velocity along the rest of the physics calculations.

    This would be equivalent to your code but more consistent:
    Code (CSharp):
    1. rigidbody.AddForce(moveVector * Time.deltaTime - rigidbody.velocity, ForceMode.VelocityChange)
    This code would also be in FixedUpdate. Note that Time.deltaTime already returns the fixed delta time when read from FixedUpdate.
     
    Reaktion likes this.
  4. shuskry

    shuskry

    Joined:
    Oct 10, 2015
    Posts:
    462
    Thanks for helping me @Reaktion @Edy :D !

    I understand why I need to put it on FixedUpdate now :)
    Thanks for all these link , I understand better how it's work !

    I will use AddForce with ForceMode.VelocityChange instead like you said. I didn't know about that thanks !
    And is it good to use this way on mobile ? I'm trying to find the more optimize way to move my player and ennemis for low end device on mobile. I need my player/ennemies to move and detect collision with projectiles or trigger collider.
     
    Last edited: May 10, 2023
    Edy and Reaktion like this.
  5. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    That's *the* way to work with physics in Unity, regardless of the target platform. Any other method will likely provide inconsistent results and/or glitches. Optimization is applied to other areas (visual effects, frame rates, etc).
     
    shuskry likes this.
  6. shuskry

    shuskry

    Joined:
    Oct 10, 2015
    Posts:
    462
    Thank you for your answer, I modified to use what you told me :D
     
    Edy likes this.