设想,当角色所在的地面平坦时,双脚和地面贴合的高度,正是胶囊体与地面接触的高度,此时没有视觉上的问题。然而,当角色所在的地面不平坦时,双脚各自所在的位置,和胶囊体与地面接触的高度是不一样的,此时就会出现“脚部陷入地下”或者“脚部悬空”的视觉问题。
先不谈“脚部悬空”的问题。对于“脚部陷入地下”,IK是解决这个问题的一个途径。 在上一篇博客中《学习UE4动画蓝图:配置手部IK》中,我已经体验了IK功能并将其配置到手部,使得角色挥拳的时候拳头会被“墙”阻挡而不至于穿墙。对于现在脚部的处理,思路上很相似:都是使用射线检测计算骨骼期望到达的位置,然后以此启用IK。但是不同的是射线的方式不同:
对于上一篇的“手部IK”:射线将从肘部射到手部靠前的位置。而对于这一篇的“脚部IK”:射线将在脚部的垂直线上,高度上从角色胶囊体与地面接触的高度到角色胶囊体半身的高度。(本篇主要参考了官方的“内容示例”:)
左/右脚的骨骼分别为foot_l/foot_r。 有一点需要注意,在foot_l这个骨骼的坐标系中,X轴(红色的)是向上的: 而在foot_r的坐标系中,X轴(红色的)是向下的: 记住这个差别。
随后,分别添加插槽LeftFootIKSocket和RightFootIKSocket: 要注意的是:插槽的位置并不是(0,0,0),而是更靠下正好到脚底板的高度。我调成了:
在之前配置手部IK时,射线操作被放到了动画蓝图的事件图表中,而现在希望能放到角色蓝图中。其实并没有严格规定必须放在哪里,可能需要根据二者的环境谁更方便来决定。在这里,由于我想访问角色胶囊体,因此我觉得在角色蓝图中访问更方便。
创建一个新的变量IKFootTraceDistance。由于它是固定的,因此在构造函数中计算赋值: 逻辑是:直接使用胶囊体组件中胶囊体的半身距离。
新建一个函数IK Foot Trace: 它将用来做左右脚的射线计算,输入是“射线距离”与“插槽的名字”,输出的是射线交点相对于骨骼的偏移: 逻辑是(图中注释框的标题描述不准确):
插槽的位置决定了射线的X、Y值高度上(Z值):GetActorLocation得到的是胶囊体中心点,此高度是中心距离,而它减去的TraceDistance正好是胶囊体的半身,因此得到的高度是不考虑IK时脚应该所在的高度。首先,添加变量记录左右脚期望偏移的长度IKoffsetLeftFoot和IKoffsetRightFoot,随后在Tick中调用刚才的IK Foot Trace函数计算(注意要填写各自的插槽名)。
和之前设置手部IK节点一样,为了调节Joint Target Location,可以先连一个简单的,进行预览观察: 不过需要注意的是它的参数:
IKBone是末端的骨骼foot_r,和之前没有区别Effector Location Space选择为了Bone Space,并且Effector Target是foor_r,这样之后输入的Vector应该是相对于这个骨骼的偏移。Joint Target Location Space选择为了Parent Bone Space,并且Joint Target选择为了thigh_r。关于Bone Space和Parent Bone Space的区别有待后续研究,但这里应该不是世界空间和组件空间,因为用于确定“大腿-膝盖-脚”这三点平面的Joint Target Location应该需要和“大腿的旋转”相关的。随后,确定一下Joint Target Location的值。
然后正式连接节点: 其中的RightFootEffectorLocation和LeftFootEffectorLocation是新的变量,将在事件图表中传入。
这里的逻辑比较简单,就是根据角色蓝图中射线计算的高度偏移,去构造骨骼期望位置的Vector。 需要注意的是,正如在 【1. 找到启用IK的骨骼名,添加插槽】 提到的,右脚骨骼坐标系中,朝上的方向是(-1,0,0),而左脚坐标系中,朝上的方向是(1,0,0)。
将角色面向模式变为向前,然后在一个斜坡上,旋转。可以看到随着脚部的高度变化,膝盖的旋转也会相应调整到期望的状态。
正如一开始讨论的,脚部贴合地面的问题包括“脚部陷入地下”和“脚部悬空”。由于射线的高度是从(脚部之上)的位置到(脚部),因此只能解决“脚部陷入地下”的问题。“脚部悬空”还是会有: 在《[UE4蓝图]虚幻4中完整实现脚部IK(二)(完结) - 知乎》中提到一个解决方法: 将人物的根骨骼朝下移动,距离刚好使那只离地面更近的脚能触及地面。 待后续实践。
