Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Something I don't understand about smoothed rotations?

Discussion in 'Physics for ECS' started by PhilSA, Jan 1, 2021.

  1. PhilSA


    Jul 11, 2013
    I need to calculate the rotation delta of a smoothed/interpolated transform from frame to frame, so that I can make another object rotate by exactly the same amount every frame. I calculate this rotation delta like this in a system that updates after TransformSystemGroup:

    Code (CSharp):
    1. [GenerateAuthoringComponent]
    2. public struct TestRotationCopier : IComponentData
    3. {
    4.     public Entity Target;
    5.     public LocalToWorld PreviousLocalToWorld;
    6. }
    8. [UpdateAfter(typeof(TransformSystemGroup))]
    9. public class CopyRotationDeltaFromInterpolationSystem : SystemBase
    10. {
    11.     protected override void OnUpdate()
    12.     {
    13.         Entities.ForEach((Entity entity, ref TestRotationCopier rotationCopier) =>
    14.         {
    15.             // Calculate rotation delta of target
    16.             LocalToWorld targetLocalToWorld = GetComponent<LocalToWorld>(rotationCopier.Target);
    17.             quaternion targetRotationDelta = math.mul(math.inverse(rotationCopier.PreviousLocalToWorld.Rotation), targetLocalToWorld.Rotation);
    19.             // Apply rotation delta to self
    20.             LocalToWorld selfLocalToWorld = GetComponent<LocalToWorld>(entity);
    21.             selfLocalToWorld.Value = new float4x4(math.mul(targetRotationDelta, selfLocalToWorld.Rotation), selfLocalToWorld.Position);
    22.             SetComponent(entity, selfLocalToWorld);
    24.             // Remember previous LtW
    25.             rotationCopier.PreviousLocalToWorld = targetLocalToWorld;
    26.         }).Schedule();
    27.     }
    28. }
    Now here's the problem: my other object that's supposed to rotate by the same amount as the tracked object rotates slightly faster, and also rotates by a huge rotation every now and then. For example, here the camera tries to track the rotation of the orange platform:

    What's weird is that if instead of using the LocalToWorld.Rotation, I just use the Rotation (from the actual transform), the issue disappears completely (but there's another issue because now my camera rotation isn't properly interpolated anymore, which means this causes visual jitter of the platform):
    Last edited: Jan 1, 2021
  2. PhilSA


    Jul 11, 2013
    I found out that scale has something to do with it. If the object that I'm trying to track the rotation of has a scale of (1,1,1), the problem disappears

    I'm guessing this has nothing to do with physics graphics smoothing, but just with me not knowing the particularities of getting LocalToWorld.Rotation when there are non-unit scales? This thread seems to mention that issue as well

    In the meantime, I've worked around the issue by getting the rotation like this instead:
    Code (CSharp):
    1. quaternion.LookRotationSafe(targetLocalToWorld.Forward, targetLocalToWorld.Up);
    Last edited: Jan 1, 2021
  3. milos85miki


    Nov 29, 2019
    Hi @PhilSA,

    That's correct, you should use quaternion.LookRotationSafe or Unity.Physics.Math.DecomposeRigidBodyOrientation to get actual rotation. We're doing the same thing in CreateRigidBodies job in BuildPhysicsWorld.
    Scale is multiplied with rotation matrix in LocalToWorld, to spare 1 matrix multiplication as you usually need to multiply with rotation and scale.

    Hoping this clarifies things, please let us know if there's anything else to help with.