Use Callbacks

If you need to act on an animation being played for a specific duration or just completed, you could just constantly check the playing FlexMotionLayer's time values as follows:

using SV.FlexMotion;
using UnityEngine;

public class CheckForCompletionUpdate : MonoBehaviour
{
    [SerializeField]
    private FlexMotionAnimator animator;

    [SerializeField]
    private AnimationClip clip;

    private FlexMotionLayer _layer;
    
    private void Start()
    {
        _layer = animator.Play(clip);
    }

    private void Update()
    {
        if (_layer?.NormalizedTime >= 1.0f)
            SomeAction();
    }

    private void SomeAction()
    {
        _layer.Stop();
        _layer = null;
    }
}

But it is less error prone and much more convenient to simply subscribe to the provided FlexMotionLayer callbacks.

There are 5 callbacks currently available:

  • OnComplete - Triggered when the animation is completed once per animation loop. As it is based on the motion duration and current time even non-looping animation can trigger the underlying event multiple times.
  • OnStopped - Triggered when the animation is stopped. Usually when another animation is played.
  • OnTime - Triggered when the specified time in second is reached.
  • OnNormalizedTime - Triggered when the specified normalized time is reached (for example 0.5f corresponds to 50%).
  • OnUpdate - Triggered every time the layer is updated.

Here is an example of how you would use these callbacks:

using SV.FlexMotion;
using UnityEngine;

public class UseCallbacks : MonoBehaviour
{
    [SerializeField]
    private FlexMotionAnimator animator;

    [SerializeField]
    private AnimationClip clip;

    private void Start()
    {
        animator.Play(clip)
            // Using a lambda expression to double the speed of the layer at 50% completion
            .OnNormalizedTime(0.5f, layer => layer.Speed = 2f)
            // Call a method when the animation is complete (will be called once per loop)
            .OnComplete(OnComplete)
            .OnStopped(layer => Debug.Log("Stopped!"));
    }

    private void OnComplete(FlexMotionLayer layer)
    {
        Debug.Log("Completed!");

        // On the third loop, stop the animation
        if (layer.NormalizedTime >= 3f)
            layer.Stop();
    }
}

This script should produce that result:

Alternatively, you can directly subscribe to the Completed and Stopped events, like you would do with any other C# event.