UnityPhysics-GameObjects icon indicating copy to clipboard operation
UnityPhysics-GameObjects copied to clipboard

Adding an interpolation for physics body

Open grapefruitlips opened this issue 11 months ago • 1 comments

Hello,

How can I add an interpolation for physics body?

PhysicsGraphicalSmoothing smoothing = new PhysicsGraphicalSmoothing()
{
    ApplySmoothing = 1,
};
new PhysicsGraphicalInterpolationBuffer
{
    PreviousTransform = Unity.Physics.Math.DecomposeRigidBodyTransform((float4x4)pb.transform.localToWorldMatrix),
    PreviousVelocity = new PhysicsVelocity(){ Linear = float3.zero, Angular = float3.zero}
};

Hot to add it to the rigidbody's entity? or to PhysicsWorld?

For example, for MotionVelocity I see we can add it like this:

var motionVelocities = PhysicsWorld.MotionVelocities;
motionVelocities[dynamicIndex] = new MotionVelocity()...

and then finding it like

int rbIndex = PhysicsWorld.GetRigidBodyIndex(new Entity() { Index = pb.Entity });
var rb = PhysicsWorld.Bodies[rbIndex];

Or how can I get access to an entity with that physics body to add a new component? like

var entityManager = Unity.Entities.World.DefaultGameObjectInjectionWorld.EntityManager;
entityManager.AddComponentData(new Entity() { Index = pb.Entity }, new PhysicsGraphicalSmoothing());
entityManager.AddComponentData(new Entity() { Index = pb.Entity }, new PhysicsGraphicalInterpolationBuffer
{
     PreviousTransform = Unity.Physics.Math.DecomposeRigidBodyTransform((float4x4)pb.transform.localToWorldMatrix),
     PreviousVelocity = new PhysicsVelocity(){ Linear = float3.zero, Angular = float3.zero},
 });

I am totally misunderstanding how it all works(

Thanks!

grapefruitlips avatar Feb 12 '25 20:02 grapefruitlips

I get it. You need to interpolate physics bodies transforms by yourself

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
/// <summary>
/// How to use TransformInterpolator properly:
/// 0. Make sure the gameobject executes its mechanics (transform-manipulations)
/// in FixedUpdate().
/// 1. Make sure VSYNC is enabled.
/// 2. Set the execution order for this script BEFORE all the other scripts
/// that execute mechanics.
/// 3. Attach (and enable) this component to every gameobject that you want to interpolate
/// (including the camera).
/// </summary>
public class TransformInterpolator : MonoBehaviour
{
   private struct TransformData
   {
       public Vector3    position;
       public Vector3    scale;
       public Quaternion rotation;
   }
 
//Init prevTransformData to interpolate from the correct state in the first frame the interpolation becomes active. This can occur when the object is spawned/instantiated.
   void OnEnable()      
    {
        prevTransformData.position = transform.localPosition;
        prevTransformData.rotation = transform.localRotation;
        prevTransformData.scale    = transform.localScale;
        isTransformInterpolated    = false;
    }
 
   void FixedUpdate()
   {
      //Reset transform to its supposed current state just once after each Update/Drawing.
       if (isTransformInterpolated)
       {
           transform.localPosition = transformData.position;
           transform.localRotation = transformData.rotation;
           transform.localScale    = transformData.scale;
 
           isTransformInterpolated = false;
       }
 
       //Cache current transform state as previous
       //(becomes "previous" by the next transform-manipulation
       //in FixedUpdate() of another component).
       prevTransformData.position = transform.localPosition;
       prevTransformData.rotation = transform.localRotation;
       prevTransformData.scale    = transform.localScale;
   }
 
   void LateUpdate()   //Interpolate in Update() or LateUpdate().
   {
       //Cache the updated transform so that it can be restored in
       //FixedUpdate() after drawing.
       if (!isTransformInterpolated)
       {
           transformData.position = transform.localPosition;
           transformData.rotation = transform.localRotation;
           transformData.scale    = transform.localScale;
 
           //This promise matches the execution that follows after that.
           isTransformInterpolated = true;
       }
 
       //(Time.time - Time.fixedTime) is the "unprocessed" time according to documentation.
       float interpolationAlpha = (Time.time - Time.fixedTime) / Time.fixedDeltaTime;
 
       //Interpolate transform:
       transform.localPosition = Vector3.Lerp(prevTransformData.position,
       transformData.position, interpolationAlpha);
       transform.localRotation = Quaternion.Slerp(prevTransformData.rotation,
       transformData.rotation, interpolationAlpha);
       transform.localScale = Vector3.Lerp(prevTransformData.scale,
       transformData.scale, interpolationAlpha);
   }
 
   private TransformData transformData;
   private TransformData prevTransformData;
   private bool isTransformInterpolated;
}

grapefruitlips avatar Feb 13 '25 14:02 grapefruitlips