Animancer的States(翻译)
Table of Contents
请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com
State
当播放一段动画剪辑(animation clip)时,Animancer会创建一个ClipState
来管理它并跟踪其进度。ClipState
是最常见的一种AnimancerState
,除此之外,有其他类型的AnimancerState
,例如Controller States
和 Mixer States
。这些用来在一个state中管理多个动画剪辑。
执行AnimancerComponent.Play
函数播放一个animation clip,就返回一个AnimancerState
对象,如下代码所示:
void PlayAnimation(AnimancerComponent animancer, AnimationClip clip)
{
// Play the animation and control its state:
var state = animancer.Play(clip);
state.Time = ...
state.NormalizedTime = ...
state.Speed = ...
state.OnEnd = ...
}
也可以自己访问和创建状态,而无需立即播放它们:
code | description |
---|---|
var state = animancer.States.GetOrCreate(clip); |
访问状态而不播放状态(该Play方法在内部使用此状态)。 |
var state = animancer.States[clip]; |
获取状态(如果存在)(否则为null)。 |
var state = animancer.States.Create(key, clip); |
即使该动画已经存在,也要创建一个新状态。注意必须为每个状态提供不同的key。 |
var state = new ClipState(animancer, clip); |
创建一个新状态而不给它一个Key。可以使用其AnimancerState.Key 属性分配一个。 |
Keys
当用AnimancerComponent.Play
方法创建一个state时,这个state存储在一个内部的Dictionary
容器中,通过指定某个key,用以在以后用这个key来检索使用该state。
- 默认地,该state所播放的那段动画剪辑所对应的AnimationClip实例对象,将作为该state的key值
NameAnimancerComponent
将重载其GetKey方法,NameAnimancerComponent
类不再使用它播放的AnimationClip对象,而是使用这个动画剪辑的名字字符串去作为key。但在启动时,可以在inspector面板中,在Animation中预先注册好这个
void PlayAnimation(AnimancerComponent animancer, AnimationClip clip)
{
// Trying to play an animation before registering it does nothing.
// 通过名字的方式试图去播一个animation clip,如果尚未注册的
// 话,通过名字是无法找到对应的animation clip去播放的
animancer.Play("Attack");
// But if you create a state with a key first, then you only need that key to play it later on.
// 如果预先创建一个state,该state通过字符串Attack作为key,指向一个clip,再调用播放接口就能正确播放了
animancer.States.Create("Attack", clip);
animancer.Play("Attack");
// Or you can create the state and set its key manually:
// 或者直接创建一个ClipState对象,然后显式地设置
var state = new ClipState(clip);
state.Key = "Attack";
}
- 如果不需要,则不需要设置
AnimancerState.Key
。可以简单地创建一个ClipState
(或其他所需的一种AnimancerState
)。并在要使用它时保留对其的引用。 - 如果要让多个state播放同一个animation clip(例如:需要在多个Layer上播放它),则需要使用不同的key注册所有状态(或根本不注册)。FadeMode.FromStart使用此选项可以使剪辑淡出,同时使另一个副本同时淡入。
Enum Keys
枚举值可以用作key,但枚举是值类型,所以用枚举做key的时候,要对它进行装箱操作。相对而言,会带来一些性能消耗
Object Keys
Another approach is to use actual objects as keys. Rather than an enum you could make a class like this: 可以创建一个显式的object来做为key,如下代码:
public static class CreatureAction
{
public static readonly object Idle = new object();
public static readonly object Walk = new object();
public static readonly object Run = new object();
// Etc.
}
这些objects实际上不会自行执行任何操作,但可以按类似于enum的方式用来作为key:animancer.States.Create(CreatureAction.Walk, _Walk)
Component Keys
如果脚本只有一个要播放的动画,则可以将其自己用作键,因此Walk脚本可以使用代码animancer.States.Create(this, _Walk);
创建state。并使用animancer.Play(this)播放animation clip。但是,如果它实际上是一个Movement将Walk和Run动画作为单独的状态进行处理的脚本,则该方法将无效。
Performance
就像其他操作一样,创建一个AnimancerState,并将其连接到“Playable Graph”需要花费一些时间。在大多数情况下,此成本很小,因此不值得考虑,因此您应该在最方便的地方创建状态。这就是为什么使用Animancer的最常见方法是直接给Play
方法传递AnimationClip实例。以便它可以为它创建一个AnimancerState(如果尚不存在),然后在以后每次播放该动画时重新使用它。
初始化启动时创建所有或大多数animancer state会增加一些复杂性,并可以提高性能,但这只能通过增加更大的负载来实现。这在加载屏幕期间可能会很好,但是如果您在游戏过程中实例化一个角色,您已经为此付出了很高的性能成本,这意味着最好不要花更多的时间来预初始化所有其他内容。预先初始化animancer satte的主要方式有两种:
- 在启动代码中(例如在
Monobehaviour
的Awake
或者Start
方法中)调用animancer.States.GetOrCreate
- 使用一个
NamedAnimancerComponent
类,并将有问题的剪辑分配到Animations检查器中的数组(或使用脚本)。这样子只会在Monobehaviour.Awake方法中简单地调用了一次GetOrCreate。 - 如果您不再需要这个AnimancerState对象,则可以调用
AnimancerState.Destroy
将其删除。销毁和随后的垃圾收集也都需要管理性能成本。
“性能基准”部分将进一步详细介绍Animancer的性能。