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. Dismiss Notice

Temp fix for Multiparent constraint scale issue.

Discussion in 'Animation Rigging' started by Ratslayer, May 14, 2020.

  1. Ratslayer

    Ratslayer

    Joined:
    Feb 6, 2014
    Posts:
    37
    Yesterday, I've filed a bug (https://fogbugz.unity3d.com/default.asp?1246893_0iui1sbfm70rrd9h) about Multiparent Constraint not working properly with uniform scaling. The gist of it can be seen in those 2 pictures:
    This is a pose with scale [1,1,1]
    No Scale.png
    This is same pose with scale [2,2,2]
    2x Scale.png
    The sword is parented to root transform in the hierarchy and parented to the right hand in the constraint.
    As you can see, there is an undesired offset between the hand and the sword. While waiting for the fix, I've decided to try one myself, so in the MultiParentConstraintJob package file, I've replaced the following lines (beginning at 72 I think):
    Code (CSharp):
    1. // Convert accumTx to local space
    2. if (drivenParent.IsValid(stream))
    3. {
    4.     drivenParent.GetGlobalTR(stream, out Vector3 parentWPos, out Quaternion parentWRot);
    5.     var parentTx = new AffineTransform(parentWPos, parentWRot);
    6.     accumTx = parentTx.InverseMul(accumTx);
    7. }
    8.  
    9. driven.GetLocalTRS(stream, out Vector3 currentLPos, out Quaternion currentLRot, out Vector3 currentLScale);
    10.  
    11. if (Vector3.Dot(positionAxesMask, positionAxesMask) < 3f)
    12.     accumTx.translation = AnimationRuntimeUtils.Lerp(currentLPos, accumTx.translation, positionAxesMask);
    13. if (Vector3.Dot(rotationAxesMask, rotationAxesMask) < 3f)
    14.     accumTx.rotation = Quaternion.Euler(AnimationRuntimeUtils.Lerp(currentLRot.eulerAngles, accumTx.rotation.eulerAngles, rotationAxesMask));
    15.  
    16. driven.SetLocalTRS(
    17.     stream,
    18.     Vector3.Lerp(currentLPos, accumTx.translation, w),
    19.     Quaternion.Lerp(currentLRot, accumTx.rotation, w),
    20.     currentLScale
    21. );
    with the following lines:
    Code (CSharp):
    1. driven.GetGlobalTR(stream, out Vector3 currentPos, out Quaternion currentRot);
    2. if (Vector3.Dot(positionAxesMask, positionAxesMask) < 3f)
    3.     accumTx.translation = AnimationRuntimeUtils.Lerp(currentPos, accumTx.translation, positionAxesMask);
    4. if (Vector3.Dot(rotationAxesMask, rotationAxesMask) < 3f)
    5.     accumTx.rotation = Quaternion.Euler(AnimationRuntimeUtils.Lerp(currentRot.eulerAngles, accumTx.rotation.eulerAngles, rotationAxesMask));
    6.  
    7. driven.SetGlobalTR(
    8.     stream,
    9.     Vector3.Lerp(currentPos, accumTx.translation, w),
    10.     Quaternion.Lerp(currentRot, accumTx.rotation, w)
    11. );
    Basically, I've removed the conversion to object's local space and just did everything in world space instead. It works for me, as the sword now scales and moves properly, but I am not sure if there are other use cases to consider. I am curious at the devs' take on this.
     
  2. simonbz

    simonbz

    Unity Technologies

    Joined:
    Sep 28, 2015
    Posts:
    295
    Hi,

    Good catch! This should indeed work with variable uniform character scale values!

    As for your solution, this will work well in most cases, but unfortunately, this breaks how positionAxesMask and rotationAxesMask are applied on the driven object. Both masks are meant to apply to local object coordinates, whereas now they will apply in world coordinates.

    However, I don't think this invalidates your changes. If you don't need masks, you can just create your own version of that constraint and remove what you don't need from it. It will surely operate faster if you do ;)
     
  3. CampbellSFletcher

    CampbellSFletcher

    Joined:
    Jul 30, 2021
    Posts:
    2
    Hey Simonbz, sorry if there is a better thread i could post this in (couldn't find one) but;
    though the issue seems fixed at runtime in rigging tool 1.1 in unity 2021, it still happens when previewing animations in the scene view, which makes it very difficult to work with. any chance this will be fixed?
    don't want to sound annoying but to be honest this basic tripping point has been the one thing stopping me from making good use of your great tool for a long time.
    let me know if you need more info!