Unity3D 中 Generic 动画导入设置和 Root Motion 之间的关系

 

Unity3D 的 Mecanim 动画系统能够直接复用 3DS MAX 中制做的动画文件中的位移,这个就是经过 applyRootMotion 来达成的,咱们只须要在使用 Animator 控制动画播放的同时,设置 Animator 的 applyRootMotion 字段为 True 就 OK 了。app

那么怎么来利用这个特性达成咱们想要的一些效果呢?这个 applyRootMotion 到底指的是啥呢?编辑器

ApplyRootMotion,从字面上理解来看,是『应用根节点的运动』,听起来貌似像那么一回事。但是咱们能够从官方文档上看到这样一段话:函数

The Root Transform is a projection on the Y plane of the Body Transform and is computed at runtime. At every frame, a change in the Root Transform is computed. This change in transform is then applied to the Game Object to make it move.oop

翻译过来的意思,应该是这样的:优化

根节点的运动变换其实就是整个物体运动变换经过 Y 轴垂直在水平面上的一个投影。根节点的运动变换在动画的每一帧中都会进行计算。计算出来的根节点变换结果都会应用在播放动画的对象上,让该对象按照根节点的运动变换进行移动。动画

这段话大致的意思就是,RootMotion 这个玩意就是做用于动画物体在 X 轴和 Z 轴上的位移的,并且这个位移是根据实际播放的动画中每一帧物体的位移在 X 和 Z 轴上投影计算出来的。spa

这个特性很是赞特别是对于某些技能动画,整个动画是有必定位移的,可是动画的位移是动做设计师在设计时根据动做须要调出来的,位移是跟动做的幅度直接相关和匹配的。翻译

那么在释放技能的时候就只须要直接播放动画,而且应用这个 Root Motion 的特性就能够很好的完成角色在播放攻击动做的同时进行移动,动做播放完毕以后就在动画结束帧角色所在的位置,切换为待机动做就 OK 了。设计

看起来很牛逼的样子对不对?是的,确实很牛逼。可是还有不少事情须要咱们都一一了解之后,咱们才能作出咱们想要的东西的。orm

下面咱们先岔开一下话题,好好说说这个 Animation Import Settings 中『Animations』Tab 页中各项设置的做用。

  • Import Animation,勾选这个才能够导入动画到 Unity 工程中;
  • Bake Animations,这个选项只在使用 Humanoid 动画而且使用到了 IK 特性的时候才可用;
  • Anim.Compression,这个是关于动画压缩选项的,默认会选择 Keyframe Reduction 这个是『压缩关键帧』,就是 Unity 会自行重采样动画的关键帧,还有两个选项『Off 和 Optimal』,一个是关闭动画压缩,一个是最优化压缩(应该是压缩效率最高,动画效果失真度可能也较高)
  • 选择了 Keyframe Reduction 或者 Optimal 压缩选项,就会有三个用于控制压缩选项的系数配置, Rotation Error,Position Error 和 Scale Error,这个三个参数默认都是 0.5,越小呢精度就越高也就是说动画的失真度越小。
  • Clips,这个下面列出了这个 FBX 文件下包含的全部动画,咱们在默认的动画文件基础上新建和删除动画片断 (Animation Clip),固然每一个动画片断都是能够指定起始帧和结束帧的; 如下的设置都是针对单个动画片断滴:
    • Loop Time,勾选这个选项以后,若是 Animator 处于播放这个动画状态时,在播放完第一遍这个动画片断以后,会自动循环从起始帧再次开始播放动画,如此循环往复。若是咱们不勾选这个选项,例如 Animator 一直处于播放这个动画的状态,那么动画会定格在动画的结束帧,直到咱们经过 Animator 切换这个 Animator 状态机的状态,切换到其余的动画;
      • Loop Pose 和 Cycle Offset,在勾选了 Loop Time 以后生效的两个选项,Loop Pose 用于控制动画循环播放时,从结束帧切换到起始帧时,动画的动做能够无缝的衔接上,Cycly Offset 就是用于控制循环的时候起始帧偏移用的;
    • Root Transform Rotation,根节点的旋转信息
      • Bake Into Pose,勾选后会将根节点每一帧的旋转方向信息烘焙到动画的骨骼运动中,在整个动画播放的过程当中,根节点的旋转信息就不会在经过 Root Motion 做用到播放该动画的 GameObject 上了,这就意味着这个动画播放的过程当中,该物体的 Transform 中的 Rotation 值不会由于动画中物体作了任何旋转而发生改变,而是会保持一个恒定的值,和该动画播放以前的旋转值保持一致;
      • Based Upon (at Start) 或者 Based Upon,根节点旋转的参考基准,有两个选项『Original 和 Root Node Rotation』这两个分别指的是动画文件中指定的旋转值和根节点旋转信息,其实我更愿意将 Original 理解为动画中原点的旋转值,由于在整个动画播放的过程当中,全部骨骼确定都会有旋转和位移的变换,可是动画的原点其实必定都是肯定的,这样理解感受更简单也更形象一些,勾选了 Bake Into Pose 以后,就会变成 Based Upon 而不勾选 Bake Into Pose 就会保持为 Based Upon (at Start),这个目前还木有理解为啥;
      • Offset,旋转角度与参考基准的偏移(以度为单位);
    • Root Transform Position(Y),根节点位移信息(Y 轴)
      • Bake Into Pose,勾选后会将根节点每一帧在垂直 Y 轴方向上的运动信息烘焙到动画的骨骼运动中,在整个动画播放的过程当中,根节点在 Y 轴方向的全部位移信息不会经过 Root Motion 做用到播放该动画的 GameObject 上,这就意味着咱们在场景中看到物体在 Y 轴上有位移,例如向上或者向下移动,可是该物体的 Transform 中的 Position 信息不会发生改变,会跟动画播放以前的 Position 信息保持一致;
      • Based Upon 或者 Based Upon (at Start),这个貌似有点不同哦,在选中 Bake Into Pose 以后会变成 Based Upon (at Start),不勾选的时候是 Based Upon,不过这个就能理解了。不烘焙的话,那么 Root Motion 中 Y 轴的变化就依赖于选择的『Original 或者 Root Node Position』的 Y 轴位移变化,若是选择烘焙的话,那么就以这个动画的起始帧的 Y 轴做为整个动画 Root Motion 的 Y 轴位移,在整个动画播放的过程当中,Y 轴的位移都是恒定不变的;
      • Offset,垂直方向上的偏移;
    • Root Transform Position(XZ),根节点位移信息(水平面,XZ 轴)
      • Bake Into Pose,勾选后会将根节点每一帧在水平面(X 和 Z 轴)方向上的运动信息烘焙到动画的骨骼运动中,在整个动画播放的过程当中,根节点在 X 和 Z 轴方向的全部位移信息不会经过 Root Motion 做用到播放该动画的 GameObject 上,这就意味着咱们在场景中看到物体在水平面上移动,可是该物体的 Transform 中的 Position 信息不会发生改变,会跟动画播放以前的 Position 信息保持一致,假如动画中物体会向前移动 3 米,咱们会看到物体在整个动画播放过程当中确实在向前移动,播放到最后一帧时确实向前移动了 3 米,可是当这个动画播放完毕以后,切换到任何其余的动画时,物体会直接闪回这个动画播放前物体所在的位置,因此一般咱们须要保留动做位移的动画都不会勾选这个选项。那这个选项有神马用捏?例如某些待机动画,咱们其实但愿物体只是作一个待机动做,可是实际上不想让物体在水平方向上有位移,这个时候就能够勾选这个选项了,到时候看起来物体就像是钉在水平面上了;
    • Mask,这个掩码主要是用于控制动画播放过程当中,各个骨骼之间的运动变换的
      • Definition,能够选择从动画文件建立也能够选择使用其余动画文件中已经建立好的配置;
      • Transform,这个就是动画文件中全部骨骼的层级关系,能够选择勾选那些须要应用动画中运动变换的骨骼;
    • Curves,这个主要用于设置某些跟动画相关的参数用,例如控制整个动画播放过程当中的速度参数之类的,在动画播放的过程当中能够经过 Animator.GetFloat(ParamName) 函数来读取曲线的值,曲线的 X 轴为动画的时间轴,Y 轴为曲线的值,曲线能够经过曲线编辑器进行增长关键点,调整曲线斜率进行编辑,读取时默认会根据当前动画播放的进度做为 X 轴的值进行读取,一个动画片断能够有多个曲线;
    • Events,这个是用于在动画播放的过程当中触发事件的,例如整个动画中有起跳和落地两个事件须要在准确的时间点触发并通知到游戏中其余的对象,那么就能够在 Events 时间轴上新增事件通知,设置好触发的方法名称和参数,在播放该动画的 GameObject 上确保有某个脚本中有与该事件通知的方法签名一致的方法就行了,当动画播放到触发通知时间时,就会向 GameObject 广播该时间通知,脚本中方法签名一致的方法就会被回调了,那咱们就能够作咱们须要作的事情了。

说了这么多貌似跟 Root Motion 不是很相关的东西,那么究竟咱们今天的主题是啥呢?确定仍是 Root Motion 这货。主要由于动画导入时的设置对于 Root Motion 的应用影响很是直接,因此前面絮絮不休地把这个动画导入设置都罗列了一遍。

回到正题,Generic 动画应用 Root Motion 有如下几个特色:

  1. Root Motion 仅仅做用于 GameObject 在 X 和 Z 轴上的位移变换,不影响 Y 轴上的位移。例如如今播放一个从地上向前空翻以后落地的动画,设置 Animator 的 applyRootMotion 为 True,也就是应用 Root Motion,那么动画在播放过程当中,物体会在水平方向和垂直方向上都按照实际动画的运动轨迹进行运动,若是将 applyRootMotion 设置为 False,那么咱们就只能看到动画在原地起跳而后再落地,动画中本来应有的在水平方向的位移就没有了;
  2. Root Motion 与导入动画时设置 Root Transform Position(XZ) 是直接相关的,若是咱们选择了将 X 和 Z 轴方向上根节点的位移烘焙到动画骨骼运动中的话,那么动画播放过程当中不论咱们是否将 Animator 的 applyRootMotion 设置为 True 仍是 False,动画播放过程当中物体在 X 和 Z 上的移动是必定的,由于这个已经被烘焙到骨骼动画中,只要动画播放,物体就会移动,可是在动画播放的过程当中 GameObject 的 Position 值不会改变,在动画结束后咱们切换到其余动画的时候,其余动画开始播放时的 GameObject 的位置会回到这个动画播放前的位置,因此若是咱们须要对某个动画应用 Root Motion 的话,那么这个动画在导入的时候就不要烘焙其在 X 和 Z 轴方向上的 Root Transform Position,让 Unity 自行根据动画中根节点的位移进行位移计算 GameObject 的位置信息;
  3. 注意 Root Motion 与 Rigidbody.Velocity 属性的关系,若是有两个动画 A 和 B,播放 A 动画的时候,但愿 A 动画应用 Root Motion,而在播放 B 动画的时候不想应用 Root Motion,那么就直接在切换到动画 B 的时候,将 Animator 的 applyRootMotion 设置为 False 就 OK 了。可是若是播放动画的 GameObject 带有 Rigidbody 组件,那么须要注意一点,在播放 A 动画时 Rigidbody 的 Velocity 并不会在切换到 B 动画时清零,也就是说若是 A 动画的运动速度较快,那么切换到 B 动画的时候,若是但愿 B 动画播放的时候 GameObject 按照本身的设定轨迹运动,就须要自行手动在切换到 B 动画以前将 Rigidbody 的 Velocity 属性清零,防止 GameObject 按照 A 动画的运动惯性继续运动。这个问题在没有 Rigidbody 组件的 GameObject 上不会存在;

这边再岔开一下,说说这个动画跟 Rigidbody 之间的关系:

  1. 若是咱们没有将 Root Transform Position 的 Y 和 XZ 轴进行烘焙的话,那么在动画播放的过程当中,Rigidbody 将会自动得到动画中物体运动的速度信息,直接经过 Rigidbody.Velocity 属性就能够得到;
  2. 若是咱们将 Y 轴进行烘焙,那么 Rigidbody.Velocity 在 Y 轴上的值将会一直为 0,对于 XZ 轴也是同样的,若是烘焙了 XZ 轴的位移,那么整个动画播放过程当中,Rigidbody.Velocity 在 X 和 Z 轴上的值都会为 0;
  3. 若是播放动画的物体没有 Rigidbody 组件,那么动画的运动都会仅仅按照动画实际的位移来进行逐帧播放,不会出现上文中提到的动画播放切换以后还存在的运动惯性问题,由于物理引擎依赖于 Rigidbody 组件,若是没有该组件,全部动画的播放都只是逐帧播放动画,不会存在速度的概念只有移动位移。
  4. Rigidbody 使用使用重力对于动画在 Y 轴上的位移没有任何影响,不管是否对 Root Transform Position 的 Y 轴进行了烘焙。

转自:http://7dot9.com/?p=528

相关文章
相关标签/搜索