Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

RigidBody.Velocity VS RigidBody.MovePosition

Discussion in 'Physics' started by folkeg, Sep 27, 2016.

  1. folkeg

    folkeg

    Joined:
    Sep 15, 2016
    Posts:
    6
    Hi I am asking a very basic question:
    Is setting velocity:
    playerRigidBody.velocity=newVector3(horizontalMove*speed,0.0f,verticalMove*speed);

    As same as:
    movement.Set (horizontalMove, 0.0f, verticalMove);
    movement = movement.normalized * speed * Time.deltaTime;
    playerRigidBody.MovePosition (playerRigidBody.position + movement);


    Thanks!
     
    DragonCoder and JayGarxP like this.
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,482
    Those are mostly equivalent when used with the correct type of rigidbody:
    • Setting velocity requires a non-kinematic rigidbody. When the velocity is applied, the rigidbody moves as driven by the physics simulation normally.
    • MovePosition works the same when the rigidbody is kinematic. In that case, you set the position on each fixed frame and the velocity gets calculated internally.
    Using MovePosition on a non-kinematic rigidbody may have issues as both you and the physics are specifying the position of the rb at the same time. Setting velocity on a kinematic rigidbody doesn't cause any effect.
     
  3. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    MovePosition doesnt use/set velocity at all. We've had this discussion previously.

    As a caveat, it may do it internally, but Velocity will read as zero.
     
  4. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,482
    Fact: calling MovePosition and MoveRotation on each FixedUpdate on a kinematic rigidbody causes both rb.velocity and rb.angularVelocity to get updated with the actual velocity of movement.
     
    FlightOfOne and BrainSlugs83 like this.
  5. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    never mind. we are talking about different rb kinematics...
     
  6. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
  7. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,482
    Oh! Yes, I had missed that conversation.
     
  8. hexagonius

    hexagonius

    Joined:
    Mar 26, 2013
    Posts:
    98
    Just to finally understand this:

    - MovePosition and MoveRotation are used in FixedUpdate on kinematic rigidbodies exclusively without changing their actual angular- and velocity
    - Setting angular- and velocity in FixedUpdate will to the same for non-kinematic rigidbodies exclusively
     
  9. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,482
    - Calling MovePosition and MoveRotation on a kinematic rigidbody in each FixedUpdate frame will cause its linear and angular velocity to be calculated and exposed (Rigidbody.velocity and Rigidbody.angularVelocity).
    - Setting velocity and angular velocity on a non-kinematic rigidbody causes an instant velocity change in that rigidbody. I think it's the same as calling AddForce with ForceMode.VelocityChange.
     
    Eralven, Malbers and Sungold like this.
  10. BroncoBilli

    BroncoBilli

    Joined:
    Oct 8, 2017
    Posts:
    90
    Old thread! Current topic! (for me)

    I have a rigged hand that follows my motion controllers, each finger bone has a twin, a following object that follows the original bone. The following object has both a capsule collider on it, and a (kinematic) RB. The game has a ball in it, with both a collider and a RB. The ball's RB's mass is set up to be 1. the hand's finger bone follower objects, their RB's masses are 100. In FixedUpdate, I call the follower's RB object with MovePosition and MoveRotation. You can see in the physics debugger window, the follower objects and colliders are moving along with the finger bones. However, when the hand smacks the ball, the ball moves VERY slowly. it's as if the internal velocity that is being set on the RB is VERY small. And in fact, it is. If I get the velocity of the RB, right after calling MovePosition and MoveRotation, AND I calculate the velocity using the current position and the last position and the deltaTime, the calculated velocity is 10000x larger in size. (0.02 instead of 0.000002). The scales of everything in the hand and the ball are '1'. The velocity I'm getting back from querying the hand bones cannot be correct ... 0.000002 in the x direction can't possibly be the velocity, that's at full swing speed.

    somebody suggested the ROOT of my hand, only, should have a RB and not each finger bone. But if I'm using a follower system, it would seem like each finger bone should have its own RB and collider. Right?
     
  11. TheJavierD

    TheJavierD

    Joined:
    Jan 6, 2017
    Posts:
    50
    I've also been relying on this automatic calculation of velocities of kinematic rigidbodies with MovePosition/Rotation

    The problem is that it's not reliable, if performance isn't great or the timestep is too small (say 0.01) most of the time the calculated velocities will be 0.
     
  12. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,482
    I've found it to be perfectly reliable, no matter the performance or the time step. If calculated velocities are 0 that means that MovePosition and MoveRotation are feed twice with the same value in two consecutive fixed time steps. Maybe you're updating your values from Update instead of FixedUpdate?
     
    ch715t0 likes this.
  13. TheJavierD

    TheJavierD

    Joined:
    Jan 6, 2017
    Posts:
    50
    Thanks Edy, you helped me out, much appreciated
     
    ch715t0 and Edy like this.
  14. eriknastesjo

    eriknastesjo

    Joined:
    Aug 16, 2018
    Posts:
    13
    Would be very thankful to Edy if you can answer this. In my Pong game I use velocity of the paddle as a parameter to steer the ball depending on if the paddle is moving up or down when the ball hits. Now I tried to use MovePosition to move paddle by touch but then I can no longer steer the ball. When I measure velocity with velocityTracker.text = myRigidbody.velocity.y.ToString(); I get 0 when I use MovePosition (in FixedUpdate and with kinematic object per your instruction) in contrast to when I use rigidbody.velocity = new vector2 etc... What am I doing wrong?
     
  15. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,482
    @eriknastesjo most probably there's something wrong in the way you apply the MovePosition command. I'd try with an absolutely simple example first, something like:
    Code (CSharp):
    1. void FixedUpdate()
    2. {
    3.     rb.MovePosition(rb.position + velocity * Time.deltaTime);
    4. }
    Then read rb.velocity from Update and verify that the value matches the magnitude of the velocity vector passed to MovePosition. Once you have this working and verified, you may then compare with your implementation and find out the way to make it work in your project.
     
  16. eriknastesjo

    eriknastesjo

    Joined:
    Aug 16, 2018
    Posts:
    13
    Feels like there is something fundamental I've missed about MovePos. I used the code below and it makes the object move but it still doesn't register any velocity in the console?
    Code (CSharp):
    1. public class SimpleMove : MonoBehaviour {
    2.  
    3.     private Rigidbody2D myRidigbody;
    4.  
    5.     // Use this for initialization
    6.     void Start () {
    7.         myRidigbody = GetComponent<Rigidbody2D>();
    8.         myRidigbody.isKinematic = true;
    9.     }
    10.  
    11.     // Update is called once per frame
    12.     void Update () {
    13.         Debug.Log(myRidigbody.velocity.x);
    14.     }
    15.  
    16.     private void FixedUpdate()
    17.     {
    18.         myRidigbody.MovePosition(myRidigbody.position + new Vector2(10f * Time.deltaTime, 0f));
    19.     }
    20. }
     
  17. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,482
    Oh! I can tell that it works in Rigidbody 3D, but I don't know if/how it works in Rigidbody2D. 2D and 3D physics systems in Unity use totally different physics engines (Box2D and PhysX, respectively).
     
  18. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,161
    Rigidbody2D.MovePosition and MoveRotation do not modify the current velocity in any way. They are a command which is only actioned during the simulation step where the following happens:

    - Linear/Angular velocities for the RB are set so that the pose moves to the position/rotation specified for the time-step specified. Also, linear and angular drag and gravity are also temporarily ignored.
    - Previous Linear/Angular velocity/drag are restored

    The linear/angular velocity persisting after the move makes little sense as it'd just mean you continue moving past the pose you specify during the next step which would mean you have to continually issue a Move or ensure you reset the velocity.

    MovePosition/Rotation is something you can do yourself though, it's just a convenience function. You can calculate the velocity required to move for a time-step easily but then you have to remove any drag/gravity otherwise that affects it.
     
  19. MegaPolicy

    MegaPolicy

    Joined:
    Oct 14, 2019
    Posts:
    2
    how i can able to add or change velocity into move position

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. [RequireComponent(typeof(Rigidbody))]
    5.  
    6. public class PlayerMoveController : MonoBehaviour {
    7.  
    8.     // PUBLIC
    9.     public SimpleTouchController leftController;
    10.     public SimpleTouchController rightController;
    11.     public Transform headTrans;
    12.     public float speedMovements = 5f;
    13.     public float speedContinuousLook = 100f;
    14.     public static float speedProgressiveLook = 3000f;
    15.  
    16.     // PRIVATE
    17.     private Rigidbody _rigidbody;
    18.     [SerializeField] bool continuousRightController = true;
    19.  
    20.     void Awake()
    21.     {
    22.         _rigidbody = GetComponent<Rigidbody>();
    23.         rightController.TouchEvent += RightController_TouchEvent;
    24.     }
    25.  
    26.     public bool ContinuousRightController
    27.     {
    28.         set{continuousRightController = value;}
    29.     }
    30.  
    31.     void RightController_TouchEvent (Vector2 value)
    32.     {
    33.         if(!continuousRightController)
    34.         {
    35.             UpdateAim(value);
    36.         }
    37.     }
    38.  
    39.     void Update()
    40.     {
    41.         // move
    42.  
    43.         _rigidbody.MovePosition(transform.position + (transform.forward * leftController.GetTouchPosition.y * Time.deltaTime * speedMovements) +
    44.         (transform.right * leftController.GetTouchPosition.x * Time.deltaTime * speedMovements));
    45.  
    46.         if (continuousRightController)
    47.         {
    48.             UpdateAim(rightController.GetTouchPosition);
    49.         }
    50.     }
    51.  
    52.     void UpdateAim(Vector2 value)
    53.     {
    54.         if(headTrans != null)
    55.         {
    56.             Quaternion rot = Quaternion.Euler(0f,
    57.                 transform.localEulerAngles.y - value.x * Time.deltaTime * -speedProgressiveLook,
    58.                 0f);
    59.  
    60.             _rigidbody.MoveRotation(rot);
    61.  
    62.             rot = Quaternion.Euler(headTrans.localEulerAngles.x - value.y * Time.deltaTime * speedProgressiveLook,
    63.                 0f,
    64.                 0f);
    65.             headTrans.localRotation = rot;
    66.  
    67.         }
    68.         else
    69.         {
    70.  
    71.             Quaternion rot = Quaternion.Euler(transform.localEulerAngles.x - value.y * Time.deltaTime * speedProgressiveLook,
    72.                 transform.localEulerAngles.y + value.x * Time.deltaTime * speedProgressiveLook,
    73.                 0f);
    74.  
    75.             _rigidbody.MoveRotation(rot);
    76.         }
    77.     }
    78.  
    79.     void OnDestroy()
    80.     {
    81.         rightController.TouchEvent -= RightController_TouchEvent;
    82.     }
    83.  
    84. }
     
    Last edited: Mar 7, 2022
  20. MegaPolicy

    MegaPolicy

    Joined:
    Oct 14, 2019
    Posts:
    2
    How i can able to add velocity here, i have to remove _rigidbody.MovePosition and then i have add velocity ? so how i can make it, sorry for my bad english..!

    Code (CSharp):
    1. void Update()
    2.     {
    3.         // move
    4.    
    5.         _rigidbody.MovePosition(transform.position + (transform.forward * leftController.GetTouchPosition.y * Time.deltaTime * speedMovements) +
    6.         (transform.right * leftController.GetTouchPosition.x * Time.deltaTime * speedMovements));
    7.  
    8.         if (continuousRightController)
    9.         {
    10.             UpdateAim(rightController.GetTouchPosition);
    11.         }
    12.     }
     
    altair2020 likes this.
  21. OneManEscapePlan

    OneManEscapePlan

    Joined:
    Oct 14, 2015
    Posts:
    216
    There is an edge case where RigidBody2D.MovePosition() resets the velocity to 0, but it's caused by using the Transform and RigidBody APIs at the same time:

    Code (CSharp):
    1.  
    2. public class RBTest : MonoBehaviour {
    3.     private void Start() {
    4.         var a = CreateRB("A. rigidBody.MovePosition()", new Vector3(0, 0, 45));
    5.         // Doing all three of these operations at once (in any order) causes the
    6.         // velocity to get reset to 0 in the next physics step, and the position
    7.         // that we specified with MovePosition() is lost.
    8.         a.transform.position = new Vector3(0, 0, -1);    // Works
    9.         a.velocity = new Vector2(0, 2);                 // Doesn't work
    10.         a.MovePosition(new Vector2(-2, 0));             // Doesn't work
    11.  
    12.         // Partially works; the velocity is not lost, but the second position is.
    13.         var b = CreateRB("B. rigidbody.position", new Vector3(0, 0, 90));
    14.         b.transform.position = new Vector3(0, 0, -1);
    15.         b.velocity = new Vector2(0, 2); // Works
    16.         b.position = new Vector2(2, 0); // Doesn't work
    17.        
    18.         // Works correctly.
    19.         var c = CreateRB("C. transform.position", new Vector3(0, 0, -60));
    20.         c.position = new Vector3(0, 0, -1);
    21.         c.velocity = new Vector2(0, 2);
    22.         c.MovePosition(new Vector2(4, 0));
    23.     }
    24.  
    25.     Rigidbody2D CreateRB(string name, Vector3 eulerAngles) {
    26.         var go = new GameObject(name);
    27.         var rb = go.AddComponent<Rigidbody2D>();
    28.         rb.isKinematic = true;
    29.  
    30.         const int dimension = 64;
    31.         var texture = new Texture2D(dimension, dimension);
    32.         var sprite = Sprite.Create(texture, new Rect(0, 0, dimension, dimension), new Vector2());
    33.         var sr = go.AddComponent<SpriteRenderer>();
    34.         sr.sprite = sprite;
    35.  
    36.         rb.transform.eulerAngles = eulerAngles;
    37.  
    38.         return rb;
    39.     }
    40. }
    41.