Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Rotation interpolation issue (Unity.Physics 0.5)

Discussion in 'Physics for ECS' started by PhilSA, Sep 18, 2020.

  1. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I upgraded to Unity.Physics 0.5 to try out interpolation, and found a case where it's not working:
    https://i.gyazo.com/5bf571df981416cac1b591ad55207200.mp4

    In this video I'm running at 5 fixed updates per second, just to make the issue really obvious. The translation of that blue platform is properly interpolated, but there seems to be an issue with the rotation even though it does move exclusively with PhysicsVelocity (Linear + Angular). What's weird is that I have other rotating objects that interpolate juste fine if they rotate only on one axis instead of all axis like this one

    Extrapolation has the same issue
     
  2. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    Weird, can you give me any more details on those specific rotating bodies? e.g. angular velocities and center of mass positions?
     
  3. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    The runtime values on the components look like this:
    https://i.gyazo.com/726233dc2bfa3e0a677c667fd00177e1.mp4

    The authoring components look like this:


    and the code that makes it move:
    Code (CSharp):
    1.  
    2. protected override void OnUpdate()
    3.         {
    4.             float deltaTime = Time.DeltaTime;
    5.             if (deltaTime > 0f)
    6.             {
    7.                 float invDeltaTime = 1f / deltaTime;
    8.                 float time = (float)World.Time.ElapsedTime;
    9.                 PhysicsWorld physicsWorld = BuildPhysicsWorldSystem.PhysicsWorld;
    10.  
    11.                 Dependency = Entities
    12.                     .ForEach((Entity entity, ref PhysicsVelocity physicsVelocity, in PhysicsMass physicsMass, in Translation translation, in Rotation rotation, in PlaygroundMovingPlatform movingPlatform) =>
    13.                 {
    14.                     float3 targetPos = movingPlatform.OriginalPosition + (math.normalizesafe(movingPlatform.TranslationAxis) * math.sin(time * movingPlatform.TranslationSpeed) * movingPlatform.TranslationAmplitude);
    15.  
    16.                     quaternion rotationFromRotation = quaternion.Euler(math.normalizesafe(movingPlatform.RotationAxis) * movingPlatform.RotationSpeed * time);
    17.                     quaternion rotationFromOscillation = quaternion.Euler(math.normalizesafe(movingPlatform.OscillationAxis) * (math.sin(time * movingPlatform.OscillationSpeed) * movingPlatform.OscillationAmplitude));
    18.                     quaternion totalRotation = math.mul(rotationFromRotation, rotationFromOscillation);
    19.                     quaternion targetRot = math.mul(totalRotation, movingPlatform.OriginalRotation);
    20.  
    21.                     RigidTransform targetTransform = new RigidTransform(targetRot, targetPos);
    22.  
    23.                     physicsVelocity = PhysicsVelocity.CalculateVelocityToTarget(in physicsMass, in translation, in rotation, in targetTransform, invDeltaTime);
    24.  
    25.                 }).ScheduleParallel(Dependency);
    26.             }
    27.         }
    28.  
     
    Last edited: Sep 18, 2020
  4. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Last edited: Sep 18, 2020
  5. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    There shouldn't be a difference between Unity/Havok Physics on this one as the smoothing should only affect the
    LocalToWorld
    component.

    Do you have a local copy of the Unity Physics package? If so, in SmoothMotionJob.Execute (Unity.Physics\ECS\GraphicsIntegration\Systems\SmoothRigidBodiesGraphicalMotion.cs) can try changing the hasInterpolationBuffer logic to use:

    Code (CSharp):
    1.                         if (hasInterpolationBuffer)
    2.                         {
    3.                             smoothedTransform = GraphicalSmoothingUtility.Interpolate(
    4.                                 interpolationBuffers[i].PreviousTransform,
    5.                                 currentTransform, NormalizedTimeAhead);
    6.                         }
    At low frequencies bodies are more likely to bounce above the ground but your rotations might look right.
    With the continuous speculative approach to collision detection and to help with this bounce above the ground, we tried to allow a bit of velocity smoothing in the interpolation. This might be introducing the rotation issues but I am surprised by the jerkiness you are seeing, especially if the dynamic cubes just thrown through the air and are not having any other forces act on them?

    When you update your own motion system? Is it in the fixed step simulation group and before BuildPhysicsWorld?
     
  6. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    ah yes that fixes it!

    yeah, the cubes are standard dynamic bodies with nothing else affecting them. Just to be clear: the video with the dynamic cubes is also running at a 5fps fixed rate. But the jitter is still there at a 60fps fixed rate (it's apparent when something perfectly smooth moves next to it)

    it's updating before the BuildPhysicsWorld (the "PlaygroundMovingPlatformSystem" highlighted here)


    ____

    I'm wondering if it would be possible to have "Interpolate" and "InterpolateWithVelocity" as two separate options to choose from in the Smoothing enum on physics bodies, even when/if this issue is fixed? I will soon implement my own simple interpolation for my characters, and I'd like to be able to configure rigidbodies to use that same kind of simple interpolation too, so that there is no visible velocity gap when a character pushes against a rigidbody
     
    Last edited: Sep 19, 2020
  7. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    @steveeHavok
    So I just finished implementing my own smoothing for my characters which kind-of copies how UnityPhysics's smoothing works, and there's one thing I don't really understand in the SmoothRigidBodiesGraphicalMotion system. It has the [UpdateBefore(typeof(EndFrameTRSToLocalToWorldSystem))] rule. But if it updates before that system, doesn't that mean that EndFrameTRSToLocalToWorldSystem will simply overwrite the LocalToWorld based on Translation+Rotation right after SmoothRigidBodiesGraphicalMotion tried to modify it for graphical smoothing? It does seem to work well in the end for smoothing translation, but I don't understand why that works and I wonder if that could be a clue

    In my own smoothing system, if I use that rule of updating before EndFrameTRSToLocalToWorldSystem, I get jitter like this:
    https://i.gyazo.com/08579e482edf5e154e7a9b5d19fad8d6.mp4

    But if I change it to update after EndFrameTRSToLocalToWorldSystem, everything becomes smooth:
    https://i.gyazo.com/67500bb1ca7b0f7b3db64a40bf638736.mp4
     
    Last edited: Sep 19, 2020
    cultureulterior and florianhanke like this.
  8. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    They are treating interpolation as a rendering concern only. TRS is not being written to by design. So their approach seems to be leave a span where rendering can read LTW and it will be interpolated, but eventually revert.

    While it's true interpolation is a rendering concern it's more complicated then that. Like not all networking sends physics some send interpolated positions that's actually very common. Cases where you need to interpolate against another already interpolated body or interpolate non physics bodies relative to physics bodies. So it bleeds out necessarily making it not just a rendering concern for all use cases.

    The only real issue I have is being so late that forces your own jobs that might need to read interpolated data or make custom modifications have to do so fairly late.

    I think I would prefer something like an InterpolatedLocalToWorld that's updated early. And then where interpolation is currently done copy ILTW to LTW. But that's also unnecessary work for all the trivial cases that will be the large majority. But for cases like ours pretty much required. Adapting everything that needs to access interpolated data to run that late is a non starter.
     
  9. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Well at least it's very straightforward to implement this ourselves if we need it. Translation & Rotation can hold the interpolated data that will be used for rendering (so no need to do anything special with LocalToWorld), while the fixed-rate data can be stored temporarily in a different component and re-applied to Translation+Rotation right before BuildPhysicsWorld. Or alternatively, there could be an interpolated entity that follows a non-interpolated entity, but that would be less efficient

    But my interrogation in last post was more about how can interpolation work right now if EndFrameTRSToLocalToWorldSystem overwrites the LocalToWorld with non-interpolated data after the SmoothRigidBodiesGraphicalMotion wrote the interpolated LocalToWorld
     
    Last edited: Sep 19, 2020
  10. romeo_ftv

    romeo_ftv

    Joined:
    Oct 20, 2009
    Posts:
    36
    [WriteGroup(typeof(LocalToWorld))]
    public struct PhysicsGraphicalSmoothing : IComponentData
     
  11. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    I don't have the latest entities or HR checked out but I would assume something changed there so that rendering is reading between interpolation and where TRS to LTW is done.