What is the relationship between Animator.velocity and AnimationStream.velocity?

Recently, I have been using Playable to create a new animation controller, and I am using AnimationScriptPlayable (ASP for short) to perform some motion corrections. However, I have noticed that in some cases, the corrections made by ASP do not take effect, and the values of Animator.velocity and AnimationStream.velocity are inconsistent.

For example, I have created a PlayableGraph with the following connections (→ represents the direction of Playable output):

AnimationClipPlayable → ASP → AnimationPlayableOutput
8958471--1230486--upload_2023-4-19_10-1-45.png

When no AnimationClip is assigned to the AnimationClipPlayable , the motion corrections made by ASP will take effect. However, when an AnimationClip is assigned to the AnimationClipPlayable , the motion corrections made by ASP will not take effect.

There is more information in these two posts:

Sample code:

using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Playables;

public struct ModifyMotionJob : IAnimationJob
{
    public void ProcessAnimation(AnimationStream stream) { }

    public void ProcessRootMotion(AnimationStream stream)
    {
        stream.velocity = Vector3.zero; // force zero velocity
        //stream.angularVelocity += Vector3.up * 180 * Mathf.Deg2Rad;
    }
}

[RequireComponent(typeof(Animator))]
public class Test : MonoBehaviour
{
    public AnimationClip clip;

    private Animator _animator;
    private PlayableGraph _graph;


    private void Awake()
    {
        _animator = GetComponent<Animator>();
        _graph = PlayableGraph.Create("ASP Test");
        _graph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);

        var acp = AnimationClipPlayable.Create(_graph, clip);
        var asp = AnimationScriptPlayable.Create(_graph, new ModifyMotionJob());
        asp.AddInput(acp, 0, 1f);
        var output = AnimationPlayableOutput.Create(_graph, "Animation", _animator);
        output.SetSourcePlayable(asp);

        _graph.Play();
    }

    private void OnDestroy()
    {
        _graph.Destroy();
    }

    private void OnAnimatorMove()
    {
        //_animator.velocity is not zero
        transform.rotation *= _animator.deltaRotation;
        transform.position += _animator.deltaPosition;
    }
}

Unity has confirmed that this is a bug: https://issuetracker.unity3d.com/product/unity/issues/guid/UUM-36098

2 Likes