Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Join us on Thursday, June 8, for a Q&A with Unity's Content Pipeline group here on the forum, and on the Unity Discord, and discuss topics around Content Build, Import Workflows, Asset Database, and Addressables!
    Dismiss Notice

Something I don't understand about smoothed rotations?

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

  1. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    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. }
    7.  
    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);
    18.  
    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);
    23.  
    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: https://i.gyazo.com/53cb69c19b435a952ae7fa72a45acbcd.mp4

    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): https://i.gyazo.com/106d9e5a5a56c4aec062d4c747ca9bb5.mp4
     
    Last edited: Jan 1, 2021
  2. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Update:
    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

    milos85miki

    Joined:
    Nov 29, 2019
    Posts:
    197
    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.