虚幻引擎4:IK脚部运动设置
翻译:王成林(麦克斯韦的麦斯威尔 ) 审校:黄秀美(厚德载物)
在经历了一番抉择后,我决定分享一下使用虚幻引擎的默认人体模型设置脚部IK的方法。
在一开始我打算将其发布在商城中,但是后来改变主意了。我花了一周的时间创建这个项目,花了两天的时间写了这篇教程。
主要特征有:
· 自动调节的碰撞胶囊高度
· 性能优化
· 跑步时腿部不会有奇怪的行为
前言
我们从一点理论开始讲起。我假设你对于IK(Inverse Kinematics,逆向运动学)已经有了一个基本的了解。
如果不是的话,花一些时间阅读一下虚幻引擎的IK设置。
大多数用户在处理虚幻引擎的IK时不知道双骨IK(Two BoneIK)的工作原理以及“关节目标(Joint Target)”是什么。
这是Ray Arnett在AnswerHub上找到的。
关节目标其实相当于Max或者Maya中的极向量(Pole Vector)。例如,在腿部或者手臂的IK设置中,膝盖或者肘部会指向关节目标。
看一下左边的图片,我正在平移一块骨头,它在UE中为目标关节,在Maya中为极向量以及在Blender中为极。
澄清一下,我在这篇教程中不会使用PixxiePane rig,尽管使用它处理引擎中的IK动画效果更佳。
加入插槽(Socket)
现在我们可以开始实际的教程部分了。
那么,首先我们为每只脚添加插槽。保留相对位置和相对旋转的引擎默认的数值和名称,即foot_ISocket和foot_rSocket。
动画蓝图
接下来我们打开动画蓝图,在这里我们可以定义一些变量并创建节点。
首先定义这些变量:
类型 | 变量名称 | 默认值 |
vector3 | LeftJointLoc | 设置为一个在动画预览中效果不错的值 |
vector3 | RightJointLoc | 设置为一个在动画预览中效果不错的值 |
float | LeftEffectorLoc | 0.0 |
float | RightEffectorLoc | 0.0 |
float | HipsOffset | 0.0 |
rotator | LeftFootRotation | 0:0:0 |
rotator | RightFootRotation | 0:0:0 |
然后按照以下图片放置并设置节点:
第一部分
第二部分
臀部的平移
脚部旋转
双骨IK
RightEffectorLoc乘以了-1,因为人体模型中的right_I骨骼是对称而来的,所以它应被翻转。
在我的这个例子中左脚的关节目标的数值为(X=-14.463602,Y=28.193642,Z=-15.975664)
右脚的数值为(X=-16.883377,Y=26.909676,Z=14.823689)
出于某些原因你的数值可能会不一样,就像我之前尝试调整这些设置想要在动画预览中实现一个不错的效果那样。
角色蓝图
定义变量
类型 | 变量名称 | 默认值 |
name | IKLeftSocket | foot_lSocket |
name | IKRightSocket | foot_rSocket |
float | IKTraceDistance | 50.0 |
float | IKHipsInterSpeed | 7.0 |
float | IKFeetInterSpeed | 13.0 |
float | IKCapsuleHalfHeight | 在构造脚本中定义 |
float | IKAdjustOffset | 2.0 |
float | IKTimeout | 0.5 |
bool | IKOptimized | true |
ref | AnimInstance | 动画实例蓝图 |
构造脚本
我们在构造脚本中存储默认半胶囊高度以便后面使用。
事件图表
我总是将世界秒数增量(World Delta Second)保存在一个名为“Get World Delta Seconds”的变量中,这样做可以很好地减少函数调用次数以及减少节点之间的连线数。
接下来我不会立即展示IK图表的内容,而是展示我用到的每一个IK函数。
IKFootTrace
IKFootTrace 第一部分
IKFootTrace 第二部分
注意注释泡中的三个本地变量,你也可以省略这些变量的定义,将它们直接连到目标函数的输入位置。这个函数的作用就是从胶囊的中间高度位置以及脚部插槽位置的X和Y发射一条射线,一直到胶囊的底部,然后减去TraceDistance(距离)变量值。
如果没有有效的碰撞,函数会返回0,否则它会将射线跟踪的终点位置(End Trace Location)从跟踪击中位置(Trace Hit Location)中刨除出去,从而将其从跟踪距离(TraceDistance)中刨除出去,只取从插槽到击中位置的距离。
然后为了调整脚部偏移量我们加入一个正数或负数值,因为胶囊通常比它内部物体要高2-3个单位。如果你使用的是不同的动画或者角色网格物体,那么该值会有所不同。
输出值为脚部偏移量和冲击法线(Impact Normal),当我们调整脚部旋转方向以符合斜面的角度时会用到它们。见下一个函数。
NormalToRotator
这个函数会将跟踪冲击法向向量转换为旋转方向。
IKUpdateFootOffset和IKUpdateFootRotation
IKUpdateFootOffset
IKUpdateFootRotation
这里没什么可多说的,只有两个功能函数,它们平缓地更新了脚部偏移量以及旋转角度。
注意:EffectorVar和RotationVar变量都是使用引用进行传递的。
IKUpdateCapsuleHalfHeight
这里我们可以看到该函数将两个参数作为输入:Hips Shift(臀部位移)和Reset To Default(重置为默认值)。
基本上当臀部/骨盆向下移动时,在碰撞胶囊的顶部和网格物体的头部之间会产生一段显著的距离。因此胶囊的高度和股骨的位移量总是呈一定比例的。
因此臀部位移是“绝对化的”,除以2是因为胶囊高度进行设置时使用的是它的半身高,然后再将它从构造脚本中定义的IKCapsuleHalfHeight中减去。
IKResetVars
该函数平缓地将变量重新设置为默认值或0,当角色开始移动时被调用,也有助于减少不自然的镜头运动。
IsMoving(纯函数)
IKUpdate
这是这篇教程的重点部分。做好准备!如我之前所说的那样,注意“本地变量”注释泡中的内容。
IKUpdate第一部分
IKUpdate第二部分
在更新动画蓝图中的脚部效应器(effector)之前,左右脚的偏移变量仍没有被限制在一个范围内。这里我们取脚部偏移量和0之间的最小值。我们使用最小值移动股骨。然后,当我们有了臀部的偏移量后,我们可以使用新的数值更新胶囊高度。
IKUpdate第三部分
我们将臀部偏移量从每只脚的效应器值中减去。这是因为如果股骨向上移动,所有的骨骼都向上移动,因此脚部也会。所以将它从脚部效应器中减去会使脚部骨骼保持在第一部分中的IKUpdate函数计算出的位置。
IKUpdate第四部分
这是这个函数的最后一部分,主要用于优化性能。我们检查了当前动画蓝图中的脚部效应器位置是否和上一次计算的位置相同。如果它们相同,自定义事件DisableIK会被触发。
IK图表
好了。现在我可以为你展示该图表的内容了。它就是一个逻辑图表。
IK图表总览
IK图表第一部分
IK图表第二部分
这里我们检查了一些条件,以查看角色是否在移动或者在转向。
事实上IK只有当角色自己转向的时候才会运行,即使该角色没有移动。EnableIK是另一个自定义事件,我们将它和上文提到的DisableIK组合使用。
IK图表第三部分
在这个部分中我们看到了一些门和事件,它们可以打开或者关闭IK。DisableIK有一个延迟,因为如果IK被立刻关闭的话UpdateIK将不会有足够的时间去更新脚部位置。IKTImeout变量表示的是在关闭IK之前需要等待的时间。
就是这些了。这是我们的最终结果。
结语
我认为我们可以进一步优化,只需要一次不错的重构。也许如果有时间的话,我可以将该项目拓展到手部。
【版权声明】
原文作者未做权利声明,视为共享知识产权进入公共领域,自动获得授权。