【Unity】Timeline探索记(3)关于Playable
写在前⾯
在前⼏次探索中,时不时都会看到Playable的⾝影,⽐如在Timeline⾯板上看到的Playable Track,在写字幕轨脚本时看到的⽅法参数Playable Graph,我翻了翻关于Playable的相关博⽂,只是浏览程度的话确实没太理解博⽂内容。
这次探索会围绕这篇展开,记下我在读的过程中哪些地⽅没读懂,以及后来看了演⽰⼯程,⾃⼰另外写了测试,来补⾜理解的过程。探索
:总的来说,Playable是⼀个系统。它⽀持动画,⽽且它是除了legacy动画、Mecanim动画外的第三种(更好的)选择。它以后还会⽀持⾳频、视频等更多功能。它的优点是,可在编辑模式下看⼤部分效果,不⽤状态机,控制得更细。
没读懂的地⽅
官⽅博⽂没有具体举例实现效果,直接放理论和代码,它讲的若⼲Playable好处我都不知道如何体现。以下是我觉得很重要但没读懂的地⽅:
【问题1】Playable Graph 怎么⽤?
【问题2】Animator怎样控制权重,Playable怎样控制权重?
【问题3】Clip怎样和Animator混⽤?
补⾜理解
环境
官⽅博⽂为了演⽰Playable Graph使⽤了⼯具,下载下来,把它安上。
官⽅博⽂中提到了,下载下来,打开⼯程看看⾥⾯有什么。
Unity2019.2.6:因为⼯具和必须在Unity2018及以上版本才可运⾏,所以我的测试⼯程都会在Unity2019.2.6版本上运⾏。(我试过把它们安到Unity2017版本上,但没有成功)
Graph Visualizer⼯具
顾名思义,这是个可视化Playable Graph的⼯具。下好该⼯具压缩包并解压后,如下图,点击Packages⾯板的加号按钮导⼊它的package.json⽂件,即可安装。安装后在菜单栏Windows -> Analysis -> Playable Visualizer打开。unity3d animation
⽰例⼯程Simple Animation
在⽰例⼯程中,有3个场景,没有说明⽂档。随便打开⼀个场景运⾏,看到了三个差不多的效果,再翻了翻它的代码,竟然⼀时不知道它要告诉我什么。
顶上三个按钮播放效果都是⼀样的
⽰例看不懂没关系,先给⾃⼰设下第⼀个测试⼩⽬标——怎样⽤Playble播放动画。毕竟要了解Playble,总得明⽩最简单的怎么播动画吧。再再具体⼀点,我设定了以下测试:
【测试1】旋转Cube
⾸先,我到了⼀篇,它有着最基本的⽤Playble播放动画代码。我稍微修改了⼀下脚本(改了Graph起名,删注释),如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Playables;
[RequireComponent(typeof(Animator))]
public class Playable_RotateCube : MonoBehaviour
{
public AnimationClip clip;
private PlayableGraph graph;
void Start()
{
graph = PlayableGraph.Create("RotateCube");
animOutput.SetSourcePlayable(clipPlay);
graph.Play();
// 另⼀种写法,更⽅便的接⼝
//AnimationPlayableUtilities.PlayClip(GetComponent<Animator>(), clip, out graph);
}
void OnDisable()
{
graph.Destroy();
}
}
我在场景中准备了Cube,和从Simple Animation⽰例⼯程拷过来的旋转动画RotateLegacy。Cube挂了上⾯的播动画脚本,Animator 组件去掉⽤不着的Animator Controller,具体设置如下:
结果运⾏时报错“ArgumentException: Legacy clips cannot be used in Playables.”,官⽅脚本放的Clip不能是Legacy类型。怎么知道⼀个Clip是不是Legacy类型呢?将该Clip的Inspector⾯板切换到Debug模式,看Legacy选项是否打钩即可,如下图。
于是,我将Clip改为RotateAnimator,可以成功运⾏。
运⾏时,Cube成功播放旋转动画
此时在Graph Visualizer窗⼝中,它的Graph如下图。如脚本中写的那样,Graph中只有⼀个AnimationOuput(它的全称是
AnimationPlayableOutput),⼀个AnimationClip(它的全称是AnimationClipPlayable)。到这⾥,能对Playable Graph有⼀个初印象,它就像它的名字⼀样,相当于⼀张图,图上有着我们设置的各种Playable节点。
【测试2】cube⼀边旋转⼀边移动
现在我不仅仅想要旋转Cube,还想要它⼀边旋转⼀边上下移动。
先不说Playable怎么实现,我都没想起怎么⽤Animator实现这个效果,所以我先去翻了翻Animator相
关资料。Animator实现主要靠在Animator Controller上加Layer。这⾥我先将原先的Controller起名为cube_1Layer,接着另外创建了⼀个Controller名为cube_2Layer,它有两层Layer,Base Layer依然只有Rotate动画,具体设置如下图:
Layer1放了Move动画,具体设置如下图:
把Cube上的Animator Controller换为cube_2Layer,直接运⾏Unity即可看到Cube边旋转边移动效果。这⾥通过修改Layer中的Weight,可以解答“【问题2】Animator怎样控制权重”(更具体的可以参考)。
怎么⽤Playable实现同样效果呢?我没有搜到直接的博⽂,但在回顾之前的时看到了InputWeight,猜测应该会⽤到它,然后我试着写出了能成功运⾏的脚本。最后,我在去看时发现官⽅早已写好种种说明,包括前⾯的实现代码,唯⼀少的就是具体例⼦。最开始的需要的程序就在Manual这⾥,也应该对照Manual阅读。和官⽅Manual相⽐,【测试1】参考的个⼈效果还不够充分,图中只有2种结点——Ouput和Clip,⽽按着Manual给的脚本,图中会有3种结点——Ouput,Clip和Mixer,如下图。
这⾥⽤的脚本如下,我除了实现播动画功能外,还加了点击按钮停⽌播放的功能。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Audio;
using UnityEngine.Playables;
///<summary>
///这篇程序可以参考官⽅ docs.unity3d/ScriptReference/Playables.PlayableGraph.Connect.html
///</summary>
[RequireComponent(typeof(Animator))]
public class Playable_RotateMoveCube : MonoBehaviour
{
public AnimationClip animClipA;
public AnimationClip animClipB;
private PlayableGraph graph;
private AnimationLayerMixerPlayable mixer;
void Start()
{
graph = PlayableGraph.Create("RotateMoveCube");
output = AnimationPlayableOutput.Create(graph, "Animation", GetComponent<Animator>());
// inputCount 可以接⼏个playable
mixer = AnimationLayerMixerPlayable.Create(graph, 3);
output.SetSourcePlayable(mixer);
AnimationClipPlayable clipPlayA = AnimationClipPlayable.Create(graph, animClipA);
AnimationClipPlayable clipPlayB = AnimationClipPlayable.Create(graph, animClipB);
// sourceOutputPort 默认为0
graph.Connect(clipPlayA, 0, mixer, 0);
graph.Connect(clipPlayB, 0, mixer, 1);
// weight填0.5f只会有⼀半效果,和我理解的a + b + c = 1不同
mixer.SetInputWeight(0, 1f);
mixer.SetInputWeight(1, 1f);
graph.Play();
}
public void ClickClose()
{
// ...这⾥暂⽆判空等检测
graph.Disconnect(mixer, 0);
graph.Disconnect(mixer, 1);
graph.DestroyPlayable(mixer);
graph.DestroyOutput(output);
// cube位置会停在销毁的时刻
}
public void ClickStopB()
{
// ...这⾥暂⽆判空等检测
mixer.SetInputWeight(1, 0f);
//graph.Disconnect(mixer, 1);
}
void OnDisable()
{
graph.Destroy();
}
}
在Cube上设置如下图:
最后在运⾏时,还发现⼀个⼩问题:Move动作和Cube实际位置不⼀致,因为动作⾥记录的是Cube世界坐标,再给Cube套个⽗物体就能解决这个问题(具体可参考)。最后,运⾏效果如下图。通过修改脚本中的InputWeight,可以解答“【问题2】Playable怎样控制权重”。
这⾥的Graph视图如下:
【测试3】Clip和Controller混⽤
为了解答“【问题3】Clip怎样和Animator混⽤”,实现要⽤到的脚本依然在Manual上可以到,如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Playables;
[RequireComponent(typeof(Animator))]
public class Playable_BlendController : MonoBehaviour
{
public AnimationClip clip;
public RuntimeAnimatorController controller;
public float weight;
private PlayableGraph graph;
void Start()
{
graph = PlayableGraph.Create("BlendController");
AnimationPlayableOutput output = AnimationPlayableOutput.Create(graph, "Animation", GetComponent<Animator>());
mixer = AnimationMixerPlayable.Create(graph, 2);
output.SetSourcePlayable(mixer);
AnimationClipPlayable clipP = AnimationClipPlayable.Create(graph, clip);
AnimatorControllerPlayable ctrlP = AnimatorControllerPlayable.Create(graph, controller);
graph.Connect(clipP, 0, mixer, 0);
graph.Connect(ctrlP, 0, mixer, 1);
graph.Play();
}
void Update()
{
weight = Mathf.Clamp01(weight);
mixer.SetInputWeight(0, 1.0f - weight);
mixer.SetInputWeight(1, weight);
}
void OnDisable()
{
graph.Destroy();
}
}
因为⽤到的Controller是前⾯Cube的cube_1Layer,所以这次我选择在Capsule上挂这个脚本,具体设置如下图:
运⾏时调节Inspector⾯板上的Weight值,可以看到Capsule变化。以下是将Weight调为0.66时的效果。“【问题3】Clip怎样和Animator 混⽤”解答完毕。
这⾥的Graph视图如下:
通过上⾯⼀系列测试,我对Graph有了⼀定了解。对于“【问题1】 Playable Graph 怎么⽤”,我的解答是:像它的名字⼀样,当⼀张图来⽤,在图上,可以到我需要的任何节点。
回到⽰例⼯程Simple Animation
在完成上⾯测试后,对着Manual再次阅读,现在是时候回到⽰例⼯程Simple Animation了。看看效果,翻翻代码,我能明⽩⽰例⼯程这3个场景到底要告诉我什么了。
场景PlayOnce 演⽰重点:简单利⽤Playable播放⼀个cube旋转动画;同时和Legacy、Mecanim⽐较。
场景Complex演⽰重点:简单利⽤Playable播放⼀个⼈形动画;同时和Legacy、Mecanim⽐较。
场景ComplexWithTransitions演⽰重点:简单利⽤Playable播放⼈形动画A,然后直接粗暴切换到动画B;同时和Legacy、
Mecanim⽐较。
没有提及的
Manual上还有很多功能例如控制时间,按序列播放动画,这⾥都没有展开,我把它们的具体实现都⼀起放在测试⼯程⾥了。
下载
我的
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论