Predicting Future Rigidbody position based on velocity

Currently I am trying to understand some about the physics concepts of unity and therefore I am implementing a simple Character Controller.

I am trying to predict the character position after the next physics update based on the set velocity.
Here is the code I am currently using:

public class MyCustomCharacterController : MonoBehaviour
{

    private float moveSpeed = 5.0f;
    private Rigidbody rigidbody;

    //input constants
    private int horizontalMovementDirection;
    private int verticalMovementDirection;

    // Use this for initialization
    void Start()
    {
        rigidbody = GetComponent<Rigidbody>();
        rigidbody.freezeRotation = true;
    }

    private int getHorizontalMovementDirection()
    {
        int direction = 0;
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            direction--;
        }
        if (Input.GetKey(KeyCode.RightArrow))
        {
            direction++;
        }
        return direction;
    }

    private int getVerticalMovementDirection()
    {
        int direction = 0;
        if (Input.GetKey(KeyCode.DownArrow))
        {
            direction--;
        }
        if (Input.GetKey(KeyCode.UpArrow))
        {
            direction++;
        }
        return direction;
    }

    private void FixedUpdate()
    {
        float velX = moveSpeed * getHorizontalMovementDirection();
        float velZ = moveSpeed * getVerticalMovementDirection();
        Vector3 velocityVector = new Vector3(velX, 0, velZ);
        rigidbody.velocity = velocityVector;
        Vector3 rbPos = rigidbody.transform.position;
        if (velocityVector.x != 0 || velocityVector.y != 0 || velocityVector.z != 0)
        {
            Debug.Log("curPos: " + rbPos.ToString("F6"));
            Debug.Log("vel: " + velocityVector + " - calculated position: " + (rbPos + (velocityVector * Time.fixedDeltaTime)).ToString("F6"));
        }

    }

    // Update is called once per frame
    void Update()
    {
        //save input
        horizontalMovementDirection = getHorizontalMovementDirection();
        verticalMovementDirection = getVerticalMovementDirection();
    }
}

The output I get is like the following:

curPos: (3.000000, 0.524603, 3.000000)
vel: (-5.0, 0.0, 0.0) - calculated position: (2.900000, 0.524603, 3.000000)
curPos: (2.904709, 0.524603, 3.000000)
vel: (-5.0, 0.0, 0.0) - calculated position: (2.804709, 0.524603, 3.000000)
curPos: (2.809418, 0.524603, 3.000000)
vel: (-5.0, 0.0, 0.0) - calculated position: (2.709418, 0.524603, 3.000000)
curPos: (2.714127, 0.524603, 3.000000)
vel: (-5.0, 0.0, 0.0) - calculated position: (2.614127, 0.524603, 3.000000)
curPos: (2.618835, 0.524603, 3.000000)
vel: (-5.0, 0.0, 0.0) - calculated position: (2.518836, 0.524603, 3.000000)
curPos: (2.523544, 0.524603, 3.000000)
vel: (-5.0, 0.0, 0.0) - calculated position: (2.423544, 0.524603, 3.000000)
curPos: (2.428253, 0.524603, 3.000000)
vel: (-5.0, 0.0, 0.0) - calculated position: (2.328253, 0.524603, 3.000000)

As you can see the first prediction is off by 0.004709 and all other calculations are correct (the error from the first calculation is just pulled through to the end)
NOTE: everytime the rigidbody starts moving, after standing still, that error occurs again.

Does anyone know why this happens?
Or am I making an obvious mistake?

An exact explanation requires an examination of the source code to the physics engine, which you can actually obtain. Unity uses PhysX, and if you’re using a recent version of Unity (likely), it’s probably PhysX 3.3 (I’d have to double check that).


However, an exact answer will be a bit unsatisfying, in part because it would take such a long time to research for what amounts to a really simple, if generalized, answer.


The documentation on Rigidbody.velocity includes a warning:


“In most cases you should not modify the velocity directly, as this can result in unrealistic behaviour. Don’t set the velocity of an object every physics step, this will lead to unrealistic physics simulation. A typical example where you would change the velocity is when jumping in a first person shooter, because you want an immediate change in velocity.”


I’ve worked on some open source physics engines as a contributor, though not PhysX. The exact reason PhysX is adding that precise value I can’t answer, but what I can tell you is that when changing velocity you’re basically injecting a value into an engine that is basically in mid-calculation from one moment to the next, and it isn’t a direct control. It is not, as the name implies and you’d probably expect, an exact and instantaneous change of the object’s velocity (which is also implied by the experiment you’re performing). This velocity value is really intended as a read-mostly property (and they hope read only), but on the occasion you might want some special effect this can perform, using it is known to produce non-realistic results because the engine ‘expects’ (or is designed) to take a force and move the object, whereas this is applying an abrupt (I’ll avoid the word instantaneous here) change in velocity that otherwise would not have an actual physical explanation. Using velocity to control an object is a bit of kludge or fudge, so it won’t work with precision. Since, as you notice, the rest of your calculations work, your test is actually a success, given that the engine isn’t expected to “like” being poked this way :wink: