# RigidBody.Velocity VS RigidBody.MovePosition

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

1. ### 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

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

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

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

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

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

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

8. ### 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

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

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

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

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

Joined:
Jan 6, 2017
Posts:
50
Thanks Edy, you helped me out, much appreciated

ch715t0 and Edy like this.
14. ### 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

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

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

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).

### 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

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;
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.     {
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);
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

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

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);
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());