如何让 Unity3D Mecanim Generic 动画支持动画中的位移

由于目前我们正在做的这个游戏中可能暂时还没有太强烈的需求去使用 Mecanim 动画系统中最新的 Humanoid 类型动画,我们首选的还会使用 Generic 动画,所以呢,前路漫漫其修远,大坑前面等你栽。 确定要使用 Generic 动画之后,那就继续呗。因为之前项目中使用的都是旧的动画系统(Legacy),所有角色和 NPC 的动画都是在原点做动作,角色和 NPC 在播放动画的同时需要通过脚本来控制角色的位移,这个要求负责程序和负责动画的童鞋密切合作把角色动画位移调整到一个协调的状态,这个当然也不是什么特别困难的事情,要不你看现在 App Store 里的所有游戏不都好好的嘛。 不过如果能让动画直接带上位移,那么程序和美术童鞋都解放了,动画设计的时候就能更大胆了,毕竟角色动画的真实位移相对于程序控制的更协调,而且大家都省了不少的事情,何乐不为啊。废话说了一大堆,好吧,回到正题。 那就做一个连续的带位移的动画吧,导入 Unity 之后,创建 Animator Controller 之后,把动作设置好,点击 Play 按钮,看看效果吧。尼玛,发现单个动画在播放的过程中角色确实发生位移了,但是每个动画结束之后回到 IDLE 状态动画的时候,角色在场景中的位置会发生一次闪回,直接重新归位到动画开始播放时角色所在的位置,并且在整个动画播放的过程中,角色的位置从未发生过变化,角色身上绑的 Capsule Collider 也完全不会移动,完全落在角色身后了。这是啥问题呢?这个问题在我使用 Humanoid 动画的时候木有出现啊,尝试再次恢复到 Humanoid 动画类型,确认了在 Humanoid 动画类型下确实不会出现这个位移闪回的问题,每个动画结束后,角色所在的位置就是动画结束时位置。 Mecanim-Generic-Rig-Apply-Root-Motion-Error 搜索良久最终找到了解决方法,其实只需要在导入动画的时候指定好动画骨骼的根节点就 OK 了。  

Generic-FBX-Import-Rig-Setting Humanoid-FBX-Import-Rig-Setting

 

 

 

 

 

咱们对比一下这两个设置的选项,其中 Humanoid 动画类型导入时,根本就不需要设置 Rig 的根节点,而 Generic 动画就需要设置,而且默认设置是 none,所以需要手动指定为模型对应骨骼的根节点。

看来 Unity 动画支持 Apply Root Motion 这个特性的实现机制就是根据骨骼在动画中的位移在引擎内进行计算滴,如果我们选择使用 Humanoid 动画的话呢,肯定需要设置一个人形的骨骼 Avatar 信息,这个 Avatar 信息中就会包含骨骼各个节点的信息,其中当然也包含了根节点(或者说已经不需要根节点了,因为所有关键的骨骼信息都会映射到 Avatar 信息上)。而对于 Generic 动画呢,Unity 自身并不清楚骨骼之间的关系,而 Apply Root Motion 这个特性就是根据骨骼位移自行计算的,那么就需要我们手动地指定动画使用的骨骼的根节点了,根据根节点在动画中的位置变化就可以动态计算出来对象在场景中实时的位置了。

下图就是修改 Root Node 设置之后动画播放时的效果了,Capsule Collider 也实时跟着动画的播放改变位置了。

Generic-Apply-Root-Motion-1 Generic-Apply-Root-Motion-2

 

 

 

 

 

 

============== 更新于 2015-01-13 11:56:41 ==============

另外,所有 Mecanim 的 Generic 动画都会有一个依赖的 Avatar Definition 信息(不知道是不是翻译成蒙皮信息),在这个 Avatar 中指定指定 Root node 就好了。

在跟我们的动画设计师沟通之后,发现其实在 3DS MAX 中制作的动画都会自动生成一个 Bip001 Footsteps 的骨骼节点,该节点直接绑在 Bip001 根节点上,在 3DS MAX 中预览动画播放的全程中,这个节点一直都是 Bip001 节点在水平面上的投影,也就意味着这个点一直只在水平面上移动,是非常适合用来做 Root Motion 应用的 Root node 的,但是在将动画导入到 Unity 中之后,我们再查看 Bip001 Footsteps 这个节点的位移和在 3DS MAX 中并不一样,并不是一直处于模型质心的正下方,所以目前还无法使用 Bip001 Footsteps 这个节点作为 Root Motion 要使用的 Root node,只能选择 Bip001 这个节点。

在我们通过设置 Animator.applyRootMotion 字段为 True 以及对动画依赖的 Avatar Definition 设置合适的 Root node 之后,动画在播放的过程中,会自动调整播放该动画的 GameObject 的 Transform 的位置信息(仅限 X 和 Z 轴)。那么在这个过程中我们能否再通过其他的方法,例如 Rigidbody.MovePosition 和 Transform.position 等方法来调整 GameObject 的 Position 呢?显然是可以的,在 Animator 应用 Root Motion 调整 GameObject 的 Position 同时,我们也可以通过其他的方法调整 GameObject 的 Position,效果是叠加的。