动画状态图

你好 我们在Playrix决定制作Unity3D 。 还有动画师。 在本文中,我将告诉您我们如何在家制作以及它是如何工作的。


当我们开始设计动画图的体系结构时,我们当然会研究其他类似物,特别是在Unity Animator上。 但是,我们希望提供一个更通用的解决方案。 与同一个Unity不同,我们可以通过控制器界面自定义动画状态。 但是首先,值得弄清楚什么是动画状态图。 如果您已经遇到过这种情况,则可以跳过介绍性部分,然后继续执行实现功能。

那么这个动画状态图到底是什么?



动画状态图允许您以图形方式表示不同动画状态之间的过渡。

以角色动画为例:


我们有一个男人的三维模型,其中有几个动画:

  • 闲置-静止不动;
  • 步行-前进;
  • 坐着
  • 你好-挥手

管理动画的经典方法如下:如果您希望对象站立-打开空闲,行走-行走,坐着-坐着。 但是这样做有一定的困难。

首先,您需要手动控制动画的持续时间和顺序。 例如,要使一个人坐下,您首先需要播放动画,他如何坐下,然后再开始播放该人已经坐在那里的循环动画。 在代码中自定义这些动画的关节既困难又不便。

其次,如果动画的结尾不匹配,则动画之间的连接会变得明显,或者我们需要在当前动画的中间添加另一个动画。 在这种情况下,根本不可能完美匹配动画。 记住旧游戏中角色动画会立即切换。

动画图旨在解决这些问题。 使用它,您无需手动操作动画,现在可以使用状态进行操作。 动画制作者和设计者的工作是如何对对象进行动画处理以达到这种状态。 现在,程序员无需考虑动画的时间和顺序,而只是指示对象应进入的状态。

同样,使用动画图,加入动画的问题也消失了。 在状态之间的过渡中,我们可以使一个动画平滑过渡到另一个动画。 这是使用权重完成的。 权重是从0到1的混合因子,其中0表示动画不以任何方式影响对象,而1则完全影响对象。

例如,步行(空转)和站立(空转)之间的过渡对设置过程非常苛刻。 在行走动画中的任何时候,角色都可以停止。 因此,过渡不是立即进行的,而是短时间的。 此时,步行权重从1减小到0,站立权重从0增大到1。重要的是权重之和等于1,否则可能会出现伪影。

一切如何运作?



图由状态和转换组成。 状态是一组动画控制器,每个动画控制器可以在对象上播放某种动画或执行某种逻辑。 控制器具有入口点和出口点-这些时刻是图形通过该控制器打开状态并相应地将其关闭的时刻。 控制器还具有更新功能,除了距最后一帧的时间间隔外,还具有过渡的权重。 要混合动画,必须将其考虑在内。

控制器具有单个接口。 此外,开发人员可以添加其控制器。 例如,您可以使控制器执行某种逻辑或在弹出窗口上设置文本,等等。 这种简单的自定义允许您非常灵活地使用动画图。

我们也有变量。 可以在外部(包括从代码中)设置这些变量,然后在控制器中读取它们。 因此,例如,您可以为处于相同状态的角色切换某种动画。 通常,您甚至可以重复通过变量和条件(例如Unity)在状态之间进行转换的范例。 结合可定制的控制器,结果非常方便。

过渡可以是任意数量。 许多过渡可以以相同的方式无限地进入和退出。 过渡确定达到状态的可能性。 例如,如果状态A和F之间没有直接转换,但是有链A→B→C→D→E→F,那么当您请求从A到F转换时,图形本身将理解它需要经历中间状态B,C,D和E。


转换具有开始间隔设置和持续时间。 随着时间的推移,一切都很简单-这是过渡的时间。 但是间隔已经更复杂了:它确定了可以开始过渡的动画可接受的时间段。

例如,为了使角色坐下,您首先需要在他坐下时播放动画,然后开始座位动画。 在这种情况下,从“坐下”到“坐下”的过渡间隔应该在动画“坐下”的末尾,以便我们可以看到它如何坐下,然后在结尾处快速但平稳地进入座椅的动画。

另一个例子:一个角色正在行走,他需要停下来。 在这种情况下,过渡开始间隔应为动画的整个长度,因为角色可以随时停止。

动画图完成所有相关工作:

  • 计划进入必要状态的方法
  • 更新当前运行状态
  • 在状态之间进行平滑过渡;
  • 调整其中的权重。

有趣的功能


Playrix引擎中有许多不同类型的动画:3D模型,脊椎,Flash,粒子效果,骨骼动画。 每种类型都有一个特定的控制器。

除了简单的动画控制器外,我们还有几个辅助控制器。 例如,随机控制器。 它可能包括其他控制器及其选择可能性的列表。 每当对象进入具有这种随机控制器的状态时,都会考虑到概率来进行随机选择,并且所选控制器开始起作用。 其余的人正在睡觉,不活跃,等待着自己的时刻。

但是有时在一种状态下,我们需要切换动画。 例如,如果几个角色具有相同的图形,并且所有角色都具有某种动作动画。 一个角色需要得到他的扫帚并开始报仇,另一个角色需要获得他的相机并开始拍照,第三个角色是吃冰淇淋。 对于这种情况,有一个特殊的控制器也包含一个控制器列表,但是与随机控制器不同,这里它根据变量选择一个控制器。

变量在图形中设置,并且可以从外部进行更改,例如从代码中进行更改。 在此示例中,使用了字符串类型,每种操作类型都对应于变量的某个值。 在游戏中创建角色时,将根据所需行为为其设置此变量。

我们还有一个可以混合多个动画的控制器。 例如,您可以混合走路,左,右和前进动画。 因此,在转弯时,您可以调整它们之间的权重,以使角色的腿不会打滑,走路看起来自然。

我们需要更深入



我们进行统一的事实有很多好处。 其中之一就是我们可以随心所欲,为所欲为。 我们希望有无限的机会来扩展动画图。

我们有一个控制器接口,有几个“开箱即用”的控制器,并且可以实现该接口并在其中做任何事情(不一定是动画):

  • 更改按钮上的文本;
  • 与层次结构中的其他对象进行交互;
  • 甚至管理另一个动画图。

我们在Wildscapes游戏中的动物园访客中使用了这种方法。 每个访问者都有两个图:一个用于动画化模型,另一个用于动画化行为。

第一张图非常简单,它控制行走,可以播放一些单独的角色动画。

第二张图要复杂得多,并且有一些行为场景。 例如,角色先走,然后坐在长椅上,向某人打招呼,拍照并继续。 这是一个单独的状态分支。

该逻辑可以放在第一列,但随后动画将被重复很多次。 但是有了两个图,一切都变得简单得多。 控制图包含一系列状态,包括并行运行的第一个图的状态。


接下来是什么?


我们的图表已经了解很多,但仍有很大的发展空间。 这些计划将几个州和一个嵌套的州进行了分组。 这将大大简化任务栏。 该计划还包括改善图形和链接显示的工作。 现在,大图上的连接类似于意大利面条(即使颜色相似),有时也很容易混淆。

Source: https://habr.com/ru/post/zh-CN471956/


All Articles