AnimationStream.SetPosition doesn't work as expected in IAnimationJob

I use Animation Job to manually set the position of a character’s bone. Here is my code:

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

public struct TransformStreamHandleJob : IAnimationJob
{
    public TransformStreamHandle handle;
    public Vector3 position;

    public void ProcessRootMotion(AnimationStream stream)
    {
     
    }

    public void ProcessAnimation(AnimationStream stream)
    {
        // Set the new position.
        handle.SetPosition(stream, position);
    }
}

[RequireComponent(typeof(Animator))]
public class TransformStreamHandleExample : MonoBehaviour
{
    public Vector3 position;

    PlayableGraph m_Graph;
    AnimationScriptPlayable m_AnimationScriptPlayable;
    public GameObject TargetBone;

    public bool ShowDebug;
    void OnEnable()
    {
        var animator = GetComponent<Animator>();

        m_Graph = PlayableGraph.Create("TransformStreamHandleExample");
        var output = AnimationPlayableOutput.Create(m_Graph, "output", animator);

      
        if (TargetBone != null)
        {
            var animationJob = new TransformStreamHandleJob();
            animationJob.handle = animator.BindStreamTransform(TargetBone.transform);
            m_AnimationScriptPlayable = AnimationScriptPlayable.Create(m_Graph, animationJob);
            output.SetSourcePlayable(m_AnimationScriptPlayable);
        }
        m_Graph.Play();
    }

    void Update()
    {      
        if (!m_AnimationScriptPlayable.IsValid())
        {
            return;
        }
        var animationJob = m_AnimationScriptPlayable.GetJobData<TransformStreamHandleJob>();
        animationJob.position = position;

        m_AnimationScriptPlayable.SetJobData(animationJob);

        if (ShowDebug)
        {
            if (TargetBone != null)
            {
                Debug.Log("Position:" + TargetBone.transform.position.ToString());

                ShowDebug = false;
            }
        }
    }

    void OnDisable()
    {
        m_Graph.Destroy();
    }
}

I set the target bone’s position to (0,0,0) every frame, but I find that the world position of the target bone is not right. The manual says that AnimationStream.SetPosition can set the world position, but it seems it doesn’t work like that. Do I misunderstand something? Thank you very much.

1 Like

Hi everybody, I solved this problem.
The first thing is if I use the animation job, I must set the Animation Stream Source: Previous Inputs.

mAnimationOutput.SetAnimationStreamSource(AnimationStreamSource.PreviousInputs);

And the most important thing is: never use the animation job in the output which has the animation clip playable or any other kind of animation playable( mixer or something…). If you want to use the animation job to modify the bone’s pose, you have to create a new output whose sorting order is greater than other outputs which have animation playable inside.

3 Likes