RigidBody.Velocity VS RigidBody.MovePosition

Hi I am asking a very basic question:
Is setting velocity:
playerRigidBody.velocity=newVector3(horizontalMovespeed,0.0f,verticalMovespeed);

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

Thanks!

2 Likes

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.

7 Likes

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.

6 Likes

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.

2 Likes

never mind. we are talking about different rb kinematics…

Here’s how to get the velocity should you need it…

Oh! Yes, I had missed that conversation.

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
  • 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.
3 Likes

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?

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.

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?

1 Like

Thanks Edy, you helped me out, much appreciated

2 Likes

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?

@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:

void FixedUpdate()
{
    rb.MovePosition(rb.position + velocity * Time.deltaTime);
}

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.

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?

public class SimpleMove : MonoBehaviour {

    private Rigidbody2D myRidigbody;

    // Use this for initialization
    void Start () {
        myRidigbody = GetComponent<Rigidbody2D>();
        myRidigbody.isKinematic = true;
    }
  
    // Update is called once per frame
    void Update () {
        Debug.Log(myRidigbody.velocity.x);
    }

    private void FixedUpdate()
    {
        myRidigbody.MovePosition(myRidigbody.position + new Vector2(10f * Time.deltaTime, 0f));
    }
}

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

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.

13 Likes

how i can able to add or change velocity into move position

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Rigidbody))]

public class PlayerMoveController : MonoBehaviour {

    // PUBLIC
    public SimpleTouchController leftController;
    public SimpleTouchController rightController;
    public Transform headTrans;
    public float speedMovements = 5f;
    public float speedContinuousLook = 100f;
    public static float speedProgressiveLook = 3000f;

    // PRIVATE
    private Rigidbody _rigidbody;
    [SerializeField] bool continuousRightController = true;

    void Awake()
    {
        _rigidbody = GetComponent<Rigidbody>();
        rightController.TouchEvent += RightController_TouchEvent;
    }

    public bool ContinuousRightController
    {
        set{continuousRightController = value;}
    }

    void RightController_TouchEvent (Vector2 value)
    {
        if(!continuousRightController)
        {
            UpdateAim(value);
        }
    }

    void Update()
    {
        // move
 
        _rigidbody.MovePosition(transform.position + (transform.forward * leftController.GetTouchPosition.y * Time.deltaTime * speedMovements) +
        (transform.right * leftController.GetTouchPosition.x * Time.deltaTime * speedMovements));

        if (continuousRightController)
        {
            UpdateAim(rightController.GetTouchPosition);
        }
    }

    void UpdateAim(Vector2 value)
    {
        if(headTrans != null)
        {
            Quaternion rot = Quaternion.Euler(0f,
                transform.localEulerAngles.y - value.x * Time.deltaTime * -speedProgressiveLook,
                0f);

            _rigidbody.MoveRotation(rot);

            rot = Quaternion.Euler(headTrans.localEulerAngles.x - value.y * Time.deltaTime * speedProgressiveLook,
                0f,
                0f);
            headTrans.localRotation = rot;

        }
        else
        {

            Quaternion rot = Quaternion.Euler(transform.localEulerAngles.x - value.y * Time.deltaTime * speedProgressiveLook,
                transform.localEulerAngles.y + value.x * Time.deltaTime * speedProgressiveLook,
                0f);

            _rigidbody.MoveRotation(rot);
        }
    }

    void OnDestroy()
    {
        rightController.TouchEvent -= RightController_TouchEvent;
    }

}

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…!
```csharp
**void Update()
{
// move

    _rigidbody.MovePosition(transform.position + (transform.forward * leftController.GetTouchPosition.y * Time.deltaTime * speedMovements) +
    (transform.right * leftController.GetTouchPosition.x * Time.deltaTime * speedMovements));

    if (continuousRightController)
    {
        UpdateAim(rightController.GetTouchPosition);
    }
}**

```

1 Like