普通视图

发现新文章,点击刷新页面。
昨天 — 2024年7月2日首页

角色动画系统

作者 云风
2024年7月2日 14:38

Ant 引擎的角色动画系统还需要完善。

之前我们用 Ant 引擎开发的游戏以机械装置为主,所以并不需要人型角色动画。对于人物角色动作的动画控制,最好有更多的引擎支持。

通常,角色逻辑上的属性和动画表现存在一个映射关系。一个角色,它逻辑上的基本属性可能只有在空间中的坐标。我们编写代码控制它时,只关心它在哪里。但是,在做画面表现时,则需要根据空间坐标这组简单属性,转换为动画播放:如果角色静止不动,就播放 idle 动画,如果正在运动,就播放 walk 动画。

在引擎底层,每帧只通过坐标这个属性来计算角色该播放哪个动画以及怎样播放,信息是不够的。通常还需要结合过去时间线上的状态变化来推算出当前状态;或是通过几个独立的逻辑属性的组合,得到动画需要的信息。

例如,可以通过空间坐标的变化过程计算出速度;根据是否处于战斗状态决定是警戒行动还是自由行动……

这种从逻辑属性数据到表现用数据的映射关系,一般使用状态机来实现。Unity 文档对此有一个很好的描述。通过这个状态机,可以生成动画系统底层每帧需要的数据,而开发者只需要简单修改逻辑上的基本属性即可。

动画系统底层看到的是 Entity 当前状态下用于动画渲染的基础数据:一个动画片段的当前帧,或是几个动画片段的加权混合。而状态机只用运行当前帧的当前状态关联的转换逻辑去加工那些基本属性输入。

因为状态机永远处于单一状态,但对于动画来说,从一种状态到另一种状态通常有一个表现过程,所以,状态机中的状态和表现上的状态是有区别的。Unity 把两者区分开,idle ,walk 这种叫 state ,从 idle 到 walk 的过渡期叫 state transition 。从状态机的实现角度看,其实它们都是状态机的节点 node 。

对于非帧动画来说,处于 state 时,通常只有一个动画片段;在 state transition 阶段,则为它连接的两个 state 的动画片段的混合。state 可以触发特定的行为 behaviour ,开发者可以围绕每个特定的 state 来编写逻辑;而 state transition 通常由几个参数控制,对开发者是透明的。

动画状态机的 transition 和动画表现上的多个动画片段混合,是不同的两个东西。

从走路到跑步的过渡阶段可以直接切换两个做好的动画片段,如果是帧动画,动画片段有若干帧构成,通常几个可以衔接在一起的片段,每个片段的最后一帧可以和第一帧衔接在一起,保证循环播放,不同动画片段的第一帧是相同的,允许片段间切换。那么,状态机的 transition 要做的工作一般是,保持上一个状态的动画片段序列播放到最后一帧,可以顺利切换到下一个状态。

以走路过度到跑步为例,状态机在更新时,如果处于走路状态,一旦发现移动速度超过跑步的阈值,就可以切换到 walk to run 这个 transition ,在这个新的 node 中,状态机会继续保持走路的帧动画片段提供给动画底层,直到一个片段周期结束,然后切换到 run 这个新 state ,新的 state 会使用跑步的动画片段从头播放。

对于骨骼动画,往往不受单一动画片段的限制。它可以将多个动画片段混合在一起。在 transition 中,可以逐帧调整多个动画片段的混合权重。

关于人物运动怎样用多个动画片段混合,这里有一篇论文 做了非常详细的解释。

如果是简单的两组动画混合,例如运动方向不变的走路到跑步的过度,使用一维的混合即可。即逐步降低前一个动画片段的权重,同时增加目标动画的权重。

而如果要考虑人物在移动过程中转向,则需要二维的插值。通常使用 Gradient Band Interpolation 。当需要考虑速度变化时,把插值放在极坐标系下效果更好。虽然这需要 O(n2) 的算法复杂度,但通过一张预运算的表,就可以减少到常数时间。

btw, 即使是在 state 中,也可以用到动画的混合。比如,负伤走路的角色和正常走路的角色表现不一样。负伤走路的动画可以是由负伤动画和行走动画叠加混合而来。

❌
❌