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.