Unity的PlayableGraph切换AnimationClipPlayable时关于RestPose的思考
问题
是这样的,我有这么个简单的应用场景,一个PlayableGraph,只有一个output为AnimationPlayableOutput,然后直接连接一个AnimationClipPlayable。现在我的需求是,Editor下,使用脚本,把它的播放状态换成我一个新的Animation Clip。
一开始我的代码是这么写的:
public class Test : MonoBehaviour
{
public AnimationClip clip;
public AnimationClip clip2;
PlayableGraph graph;
// Start is called before the first frame update
void Start()
{
// 创建一个PlayableGraph
graph = PlayableGraph.Create("AnimationClipPreviewer");
graph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);
// 基于playableGraph创建一个动画类型的Output节点,名字是Animation,目标对象是物体上的Animator组件
AnimationPlayableOutput playableOutput = AnimationPlayableOutput.Create(graph, "Animation", this.GetComponent<Animator>());
AnimationClipPlayable clipPlayable = AnimationClipPlayable.Create(graph, clip);
playableOutput.SetSourcePlayable(clipPlayable);
graph.Play();
}
// Update is called once per frame
void Update()
{
// 按T的时候, 直接切换到clip2
if (Input.GetKeyDown(KeyCode.T))
{
// 切换播放的Clip
var output = graph.GetOutput(0);
graph.DestroyPlayable(playableOutput.GetSourcePlayable());
AnimationClipPlayable clipPlayable = AnimationClipPlayable.Create(graph, clip2);
clipPlayable.SetTime(0);
playableOutput.SetSourcePlayable(clipPlayable);
graph.Play();
}
}
}
这样写,能切换动画,但是有问题,问题在于,它从ClipA切换到ClipB的时候,不是从Rest Pose切换到B的,而是从A的对应时间的Pose切换到B的,这样可能A的动画改变了部分关节数据,B又没有改动到它们,就会出问题。
解决思路
我想到Playable API可以模拟Unity的Animation组件,应该不至于要我去手动切换动画的时候Reset Pose,所以我尝试着用MixerPlayable,
使用这行代码mixer.SetInputWeight(0, 0f);
,我发现角色被Unity Reset了Pose
所以我的代码如下,结果是对的,这下不用自己写Reset Pose的代码了,舒服了:
public class Test : MonoBehaviour
{
public AnimationClip clip;
public AnimationClip clip2;
PlayableGraph graph;
private AnimationMixerPlayable mixer;
// Start is called before the first frame update
void Start()
{
// 创建一个PlayableGraph
graph = PlayableGraph.Create("AnimationClipPreviewer");
graph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);
// 基于playableGraph创建一个动画类型的Output节点,名字是Animation,目标对象是物体上的Animator组件
AnimationPlayableOutput playableOutput = AnimationPlayableOutput.Create(graph, "Animation", this.GetComponent<Animator>());
AnimationClipPlayable clipPlayable = AnimationClipPlayable.Create(graph, clip);
mixer = AnimationMixerPlayable.Create(graph, 1);
graph.Connect(clipPlayable, 0, mixer, 0);
mixer.SetInputWeight(0, 1);
// 基于本组件已经索引好的AnimationClip创建一个AnimationClipPlayable
// 将playable连接到output
playableOutput.SetSourcePlayable(mixer);
// 播放这个graph
graph.Play();
}
// Update is called once per frame
void Update()
{
// 按T的时候, 直接切换到clip2
if (Input.GetKeyDown(KeyCode.T))
{
// 切换播放的Clip
var output = graph.GetOutput(0);
mixer.SetInputWeight(0, 0f);
graph.DestroyPlayable(mixer.GetInput(0));
AnimationClipPlayable clipPlayable = AnimationClipPlayable.Create(graph, clip2);
graph.Connect(clipPlayable, 0, mixer, 0);
mixer.SetInputWeight(0, 1);
clipPlayable.SetTime(0);
// 播放这个graph
graph.Play();
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本