Search Unity

Which is the best way to make an avatar point a target?

Discussion in 'Animation' started by salvolannister, May 6, 2022.

  1. salvolannister

    salvolannister

    Joined:
    Jan 3, 2019
    Posts:
    50
    PointingAnimation.png ANIMATE AN AVATAR IN ORDER TO POINT TO A TARGET AND LOOK NATURAL
    I would like to animate a character in order to make it point a target with a finger when I select an object, and I am looking for the best/natural way to do it

    (Picture attached)


    I ANIMATED IT, BUT THE ARM POINTS THE TARGET TO FAST
    To animate the character I am using:
    - unity 2019,
    - the package FAST IK with the script FastIKCCD.cs
    - the full body avatar from Ready Player Me
    - Animation Controller

    I created an animator controller with two layer: first layer has an idle animation and is set to additive, second layer has two state: an idle state with no clip and a Pointing state with a grip animation clip ( index finger outstretched) The second state is set with weight=1, an avatar mask concerning only the rx hand and is override.

    To make the rx arm and consequently the rx hand index finger point to the target I applied to the second bone of the index finger ( second of four bones) the script FASTIKCCD with iterations= 10 and chainlenght = 3 from the FastIK package.

    THE PROBLEM
    The result is not bad, but the arm switches from the idle position, driven from the animator, to the pointing position too fast and I am having big troubles to slow it down since the inverse kinematic algorithm happens in lateUpdate.

    I would like to understand:
    - If what I wrote is clear enough to get some help ( :') )
    - If I used the right approach
    - Ideas on how to slow the algorithm fix this fast movement

    The result is not bad, but the animation

    The Algorithm used with the class FastIKCCD.cs

    Code (CSharp):
    1. public class IKCCD : MonoBehaviour
    2. {
    3.     public int ChainLength = 2;
    4.     public Transform Target;
    5.     protected Quaternion TargetInitialRotation;
    6.     protected Quaternion EndInitialRotation;
    7.     public Transform Pole;
    8.     protected float CompleteLength;
    9.  
    10.     public int Iterations = 10;
    11.     public float Delta = 0.001f;
    12.  
    13.     protected Transform[] Bones;
    14.     //protected Quaternion[] InitialRotation;
    15.  
    16.  
    17.     // Start is called before the first frame update
    18.     void Awake()
    19.     {
    20.         //initial length
    21.         Bones = new Transform[ChainLength + 1];
    22.         //InitialRotation = new Quaternion[ChainLength + 1];
    23.         TargetInitialRotation = Target.rotation;
    24.         EndInitialRotation = transform.rotation;
    25.  
    26.         var current = transform;
    27.         CompleteLength = 0;
    28.         for (int i = ChainLength - 1; i >= 0; i--)
    29.         {
    30.             CompleteLength += (current.position - current.parent.position).magnitude;
    31.             Bones[i + 1] = current;
    32.             Bones[i] = current.parent;
    33.             //InitialRotation[i + 1] = current.rotation;
    34.             //InitialRotation[i] = current.parent.rotation;
    35.             current = current.parent;
    36.         }
    37.         if (Bones[0] == null)
    38.             throw new UnityException("The chain value is longer than the ancestor chain!");
    39.     }
    40.  
    41.     // Update is called once per frame
    42.     void LateUpdate()
    43.     {
    44.         //CCD
    45.         var lastBone = Bones[Bones.Length - 1];
    46.  
    47.         //for (var i = 0; i < Bones.Length; i++)
    48.         //  Bones[i].rotation = InitialRotation[i];
    49.  
    50.         for (int iteration = 0; iteration < Iterations; iteration++)
    51.         {
    52.             for (var i = Bones.Length - 1; i >= 0; i--)
    53.             {
    54.                 //https://www.youtube.com/watch?v=MA1nT9RAF3k
    55.  
    56.                 if (i == Bones.Length - 1)
    57.                 {
    58.                     Bones[i].rotation = Target.rotation * Quaternion.Inverse(TargetInitialRotation) * EndInitialRotation;
    59.                 }
    60.                 else
    61.                 {
    62.                     Bones[i].rotation = Quaternion.FromToRotation(lastBone.position - Bones[i].position, Target.position - Bones[i].position) * Bones[i].rotation;
    63.  
    64.                     //jitter to solve strait line
    65.                     //if (iteration == 5 && i == 0 && (Target.position - lastBone.position).sqrMagnitude > 0.01f && (Target.position - Bones[i].position).sqrMagnitude < CompleteLength * CompleteLength)
    66.                     //    Bones[i].rotation = Quaternion.AngleAxis(10, Vector3.up) * Bones[i].rotation;
    67.  
    68.                     //move towards pole
    69.                     if (Pole != null && i + 2 <= Bones.Length - 1)
    70.                     {
    71.                         var plane = new Plane(Bones[i + 2].position - Bones[i].position, Bones[i].position);
    72.                         var projectedPole = plane.ClosestPointOnPlane(Pole.position);
    73.                         var projectedBone = plane.ClosestPointOnPlane(Bones[i + 1].position);
    74.                         if ((projectedBone - Bones[i].position).sqrMagnitude > 0.01f)
    75.                         {
    76.                             var angle = Vector3.SignedAngle(projectedBone - Bones[i].position, projectedPole - Bones[i].position, plane.normal);
    77.                             Bones[i].rotation = Quaternion.AngleAxis(angle, plane.normal) * Bones[i].rotation;
    78.                         }
    79.                     }
    80.                 }
    81.  
    82.  
    83.                 //close enough?
    84.                 if ((lastBone.position - Target.position).sqrMagnitude < Delta * Delta)
    85.                     break;
    86.             }
    87.         }
    88.  
    89.     }
    90.  
    91.  
    92. }
     
    Last edited: May 24, 2022