Search Unity

animator.MatchTarget weird behaviour with loops

Discussion in 'Animation' started by martin-lizee, Dec 19, 2017.

  1. martin-lizee

    martin-lizee

    Joined:
    Nov 12, 2014
    Posts:
    1
    Hi,

    I have been trying to isolate some weird behaviour with MatchTarget in animation loops in Unity 2017.1.0p4

    Here is a video showing the problem:



    We can clearly see that the Unity Target moves to strange places after the first loop.


    Here is the code:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class TestMatchTarget : MonoBehaviour
    4. {
    5.     Animator animator;
    6.     Vector3 target;
    7.  
    8.     // The following controller on a character with an animator playing a looped
    9.     // walk animation should look like a walking stairs.
    10.     // The system presents a unexpected behaviour after the first loop.
    11.     // When we remove the looping of the animation by constantly resetting it, it works. (but its a hack)
    12.     // How can we use MatchTarget with looping animation?
    13.  
    14.     // Set the following variable to true or false to test with and without looping
    15.     public bool removeLooping = false;
    16.  
    17.     private void Awake()
    18.     {
    19.         animator = GetComponent<Animator>();
    20.     }
    21.  
    22.     private void Update()
    23.     {
    24.         if (!animator.isMatchingTarget)
    25.         {
    26.             float normalizeTime = Mathf.Repeat(animator.GetCurrentAnimatorStateInfo(0).normalizedTime, 1f);
    27.             float loopCount = animator.GetCurrentAnimatorStateInfo(0).normalizedTime - normalizeTime;
    28.  
    29.             if (normalizeTime > 0.05f && normalizeTime < 0.1f)
    30.             {
    31.                 Debug.Log("RightFoot");
    32.                 target = transform.position + new Vector3(0f, 0.2f, 0.8f);
    33.                 animator.MatchTarget(
    34.                     target,
    35.                     Quaternion.identity,
    36.                     AvatarTarget.RightFoot,
    37.                     new MatchTargetWeightMask(Vector3.one, 0f),
    38.                     0.2f, 0.35f);
    39.             }
    40.  
    41.             if (normalizeTime > 0.55f && normalizeTime < 0.6f)
    42.             {
    43.                 Debug.Log("LeftFoot");
    44.                 target = transform.position + new Vector3(0f, 0.2f, 0.8f);
    45.                 animator.MatchTarget(
    46.                     target,
    47.                     Quaternion.identity,
    48.                     AvatarTarget.LeftFoot,
    49.                     new MatchTargetWeightMask(Vector3.one, 0f),
    50.                     0.7f, 0.85f);
    51.             }
    52.         }
    53.  
    54.         if (removeLooping)
    55.         {
    56.             animator.ForceStateNormalizedTime(Mathf.Repeat(Time.time, 1f));
    57.         }
    58.     }
    59.  
    60.     void OnDrawGizmos()
    61.     {
    62.         Gizmos.color = Color.yellow;
    63.         Gizmos.DrawWireSphere(target, 0.1f);
    64.     }
    65.  
    66. }
    Any idea on how to use MatchTarget with loops?
     
  2. Whatever560

    Whatever560

    Joined:
    Jan 5, 2016
    Posts:
    519
    The last value of the matchtarget should be > 1 if you want to interact with other states of loops, shouldn't it ?

    Anyway I struggle with match target and loops just as you.
     
    Last edited: May 9, 2018
  3. froilan_dE_dios

    froilan_dE_dios

    Joined:
    Jul 28, 2015
    Posts:
    17
    I did something very similar when I tried to do ladder climbing for a third person project.

    Not sure but it seems that the first MatchTarget call needs to be completely concluded / finished before the next one in the loop otherwise the succeeding calls will fail. I ended up using IKTargets instead, which if you think about it, is more appropriate in this kind of situation.
     
  4. scarofsky

    scarofsky

    Joined:
    Sep 29, 2016
    Posts:
    11
    I encounter exactly the same problem as you. Although I use customYieldInstruction to wait until previous targetMatching is done, it seems not working either. And the most disappointing thing is that it is too hard to find an official explanation. Am I missing something?
     
  5. Tiernan98

    Tiernan98

    Joined:
    Jul 11, 2017
    Posts:
    42
    Bumping this because I am having this issue with a wall climbing animation. For context, there is a wall-climbing loop and there's a "step height" on the wall, kind of like a ladder, and target matching mitigates the floating-point error that accumulates over time. As the above poster said, it doesn't matter if the previous match completed or nto.

    For now, I am going to try to have two states of the same animation and switch back and forth between them.

    Also as a side note, I think the target matching in Mecanim is very unintuitive. I would prefer to see it as some sort of property on an animation in the GUI that you could call assign a function pointer to. This way we wouldn't have the messy target matching checks in the middle of the player states.
     
  6. SuspectA

    SuspectA

    Joined:
    Apr 17, 2020
    Posts:
    1
    Wow, I struggled with this for way too long and this is one of the only posts I could find anywhere on this bug (feature?)
    I realize this is from 2017 but I have a fix. For looping animations the normalized time is not reset to 0 at the replay of each animation. It continues to count up past 1.0. You just need to offset the start and end time by the normalized time. In the example shown you just need to subtract how many loops you've already been through.

    Code (CSharp):
    1. float loopOffset = Mathf.Ceil(animator.GetCurrentAnimatorStateInfo(0).normalizedTime);          
    2. animator.MatchTarget(pawn.test.position, pawn.test.rotation, AvatarTarget.Root, new MatchTargetWeightMask(Vector3.one, 1f), 0f - loopOffset, 1f - loopOffset, false);
    EDIT:
    It looks like I was too hasty in posting this. I believe I'm on the right track but this fix requires some refinement. I'll leave it up in case anyone makes better use of the lead
     
    Last edited: Oct 15, 2021