Search Unity

Rigidbody interpolation and velocity

Discussion in 'Physics' started by trigraph, Apr 24, 2017.

  1. trigraph

    trigraph

    Joined:
    Jan 24, 2017
    Posts:
    15
    Hello. I'm wondering how to get access to a rigid body's interpolated velocity in C#. The game I'm working on has a camera that follows the player at an offset based on the player's velocity. I have interpolate set to on for the rigid body. Physics gets updated in the fixed update, and the camera update is set to occur after the player is updated.

    This all works very well except for a slight (understandable, but undesirable) jitter at 30fps because of the velocity-based offset I apply... My understanding is that the interpolated position is stored in the GameObject's transform, while the rigid body's position is in sync with the physics time step.

    The problem is there's no time-derivative transform in the GameObject where I can access the interpolated velocity...which I would hope is available somewhere. In short, taking the velocity from the rigid body is (very probably)causing the jitter cuz it's on the physics update time step. It's all nice and smooth without the offset being proportional to velocity.

    Any thoughts or advice would be appreciated. Thanks :)
     
  2. Tugrul_512bit

    Tugrul_512bit

    Joined:
    Apr 9, 2016
    Posts:
    46
    Did you try to make it yourself by using 5-point stencil? Or any odd-point derivative?
     
  3. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    The velocity doesn't get interpolated, only the position.

    You may read the latest two interpolated positions (from transform.position), then get the velocity out of them as velocity = (currentPosition - lastPosition) / Time.deltaTime.
     
  4. trigraph

    trigraph

    Joined:
    Jan 24, 2017
    Posts:
    15
    Turns out I didn't have forum response notifications turned on. So, the only thing with the v=delta p / delta t method is it won't produce the same velocities that the PhysX intergrator does (the physics engine uses something much fancier than Euler).. so I still get the slight lack of smoothness (I did try it btw).

    I do have access to the rigid-body velocities in the fixed update, so I can, by taking some care with timing, do piecewise interpolation, and then do lookups in the main non-fixed time update... but that would all be unnecessary if Unity gave access to the interpolated velocities as reported by the physics when it integrates the accelerations. I think I was hoping for some secret method to retrieve them ;)

    Unity 'could' put them in the rigid-body (for access in the regular Update) if they didn't want to pollute the transform...

    Thanks for the responses :)
     
  5. trigraph

    trigraph

    Joined:
    Jan 24, 2017
    Posts:
    15
    Alright... maybe this will help others. The code below is fairly simple and works really well for my situation. Not that it matters, but it's running on Android with a targeted framerate of 30 and vsync on (well, vsync on does matter). The main caveat of the code below is that it uses Time.time and Time.fixedTime which are floats... assuming a little over 6 significant decimal digits, you're in the order of millisecond accuracy after an hour or so... I haven't bothered trying to accumulate the total times in a double, but it might not be a bad idea.

    The rigidBody needs to be set to interpolate in the inspector. Accessing the position outside of fixed update should be done with the object's transform (not the rigid body's). Accessing the velocity outside of fixed update should use the vinterp variable below. It is OK to access it in LateUpdate as Time.deltaTime is the same.

    vinterp lags in time just like the position does when using interpolation... but no more jitters :)

    Code (csharp):
    1.  
    2. Rigidbody rigidBody;
    3. Vector3 v0;                // Earliest rigid body vel sample.
    4. Vector3 v1;                // Latest vel sample separated by fixedDeltaTime.
    5. Vector3 vinterp;         // For use in Update (or LateUpdate if it's a camera).
    6.  
    7. void Start()
    8. {
    9.     rigidBody = GetComponent<Rigidbody>();
    10.  
    11.     // Assume starting at rest.
    12.     v0 = Vector3.zero;
    13.     v1 = Vector3.zero;
    14.     vinterp = Vector3.zero;
    15. }
    16.  
    17. void Update()
    18. {
    19.     // deltaTime will never be bigger than fixedDeltaTime.
    20.     float deltaTime = Time.time - Time.fixedTime;
    21.     float t = deltaTime/Time.fixedDeltaTime;
    22.  
    23.     // Interpolated velocity will always be fixedDeltaTime later.
    24.     vinterp.x = Lerp(v0.x, v1.x, t);
    25.     vinterp.y = Lerp(v0.y, v1.y, t);
    26.     vinterp.z = Lerp(v0.z, v1.z, t);
    27. }
    28.  
    29. void FixedUpdate()
    30. {
    31.     v0 = v1;
    32.     v1 = rigidBody.velocity;
    33. }
    34.  
     
    Alex_Galvez likes this.