一般动画机
本章节介绍的动画方法,都是基于 MilInstantAnimator
,也就是一般动画机。
本小节将展开介绍一般动画机的其他机制,下文出现的方法除标注”*“外均基于流式接口设计,即方法本身的返回值也是一个 MilInstantAnimator
。
例如,我们在前面小节提到的 Then
、ThenOneByOne
、And
都属于流式接口,也就是说,你可以对 MilInstantAnimator
进行任意的如下所示的方法调用嵌套:
MAni.Make(
...
).MethodA(...)
.MethodB(...)
.MethodC(
...
).Play();
生命周期
默认情况下,一般动画机会在当前场景被卸载时自动停止播放,避免一些仍未播放结束的动画操作已被卸载的物体。
若你希望动画机不会在场景被卸载时自动停止,例如你正在对 DontDestroyOnLoad
的物体执行动画操作,则可调用方法:
DontStopOnLoad()
播放相关
令动画机循环播放:
EnableLooping()
暂停动画机*:
Pause()
停止动画机*:
Stop()
停止动画机,并复原动画机的改动*:
Reset()
时间源
默认情况下,一般动画机将使用 UnscaledTime
更新动画,这意味着,它不会受到 Time.timeScale
的影响。
如果你希望动画受其影响,可调用:
SetTimeSource(TimeSource.ScaledTime);
重置模式
一般动画机会在动画从头开始播放时自动调用一次 Reset()
,而”复原动画机的改动“的程度取决于”重置模式“。
重置模式分为以下两种:
-
ResetToOriginalState(默认)
该模式会将 动画机操作的对象的相关属性 还原至 开始播放时刻记录的属性状态。
-
ResetToInitialState
该模式会将 动画机操作的对象的相关属性 还原至 动画机在0s时刻时所有动画描述的属性的状态。
可以使用该方法设置重置模式:
UsingResetMode(AnimationResetMode.ResetToInitialState);
- 无开始值的动画始终使用
ResetToOriginalState
模式重置,无视ResetToInitialState
的设定。 - 混合模式为
Additive
的动画始终使用ResetToOriginalState
模式重置,无视ResetToInitialState
的设定。 - 由于
Play()
方法是将动画机的动画任务提交,下一帧才会开始播放,有时可能会出现一种情况:你把 Canvas 显示出来了,但是动画下一帧开始播放,用户在那一帧突然看见了界面的骨架状态。为了规避这种情况,有两种解决办法:- 使用
PlayImmidiate()
方法播放,使其在当前帧就应用动画状态。 - 使用
ResetToInitialState
的重置模式,动画虽然在下一帧才开始播放,但是 重置操作 是在当前帧完成的,设定此重置模式可以立刻将其变化至 动画 0s 时刻的状态,避免穿帮。
- 使用
无开始值的动画机的复用
看完重置模式的介绍,你可能就会发现,如果你复用一个包含无开始值的动画的动画机,它会将对象状态还原至动画记录前的状态,这显然不是我们想要的。
此时,对于这种需求,我们在调用 Play
函数播放时,要显式地传入 revertToChanges
参数为 false
,使其不重置 无开始值 的动画做的修改:
Play(null, false);
延后上一组动画
动画描述相关的方法,除了 Then
、ThenOneByOne
、And
,还有最后的 Delayed
。
它会将紧邻的上一组动画整体延后播放指定秒数,例如:
MAni.Make(
1f / ballSpriteRender.MQuad(x => x.color, Color.clear, Color.white),
1f / music.MQuad(x => x.volume, 0f, 1f)
).Then(
2f / ballTransform.MQuad(x => x.position, Vector3.zero, Vector3.one * 3f),
1f + 0.5f / ballTransform.MQuad(x => x.localScale, Vector3.one, Vector3.one * 2f)
).Delayed(1f)
.ThenOneByOne(
1f / camera.MQuad(x => x.fieldOfView, 6f, 4.5f),
1f / camera.MQuad(x => x.localEulerAngles, Vector3.zero, new Vector3(0, 0, 20f))
).Play();
等价于:
MAni.Make(
1f / ballSpriteRender.MQuad(x => x.color, Color.clear, Color.white),
1f / music.MQuad(x => x.volume, 0f, 1f)
).Then(
// 注意这一组动画的 offset 变化
1f + 2f / ballTransform.MQuad(x => x.position, Vector3.zero, Vector3.one * 3f),
2f + 0.5f / ballTransform.MQuad(x => x.localScale, Vector3.one, Vector3.one * 2f)
).ThenOneByOne(
1f / camera.MQuad(x => x.fieldOfView, 6f, 4.5f),
1f / camera.MQuad(x => x.localEulerAngles, Vector3.zero, new Vector3(0, 0, 20f))
).Play();