ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

UE4 Foot IK实战:用Two Bone IK与地面法线实现斜坡脚部贴合

2026/9/15 13:43:50 拓冰建站 浏览量
UE4 Foot IK实战:用Two Bone IK与地面法线实现斜坡脚部贴合 先说结论UE4里做Foot IK最难的不是把脚“压”到地面上而是让脚掌像真人一样顺着斜坡转过去。很多项目做到一半发现角色站在30度的坡上脚是够着地了但整只脚还是水平悬空一眼假。这篇就把我在项目里踩完坑的一套做法放出来用动画蓝图的Two Bone IK做位置用地面Hit Normal做旋转双管齐下解决斜坡、台阶、碎石路的脚部贴合问题。适合正在做第三人称动作、移动端射击或者任何需要角色脚部自适应地形的朋友参考。1. 先搞清楚Foot IK到底在解决什么问题1.1 平地动画放到斜坡上的两个漏洞动画师在混合空间里K的走路、跑步、待机动画默认场景都是平地。角色站在斜坡上时会出现两个非常明显的问题第一个是高度差。左脚在坡底右脚在坡顶可平地动画要求两脚在同一水平高度于是低处那只脚悬空高处那只脚陷进地面。第二个是角度差。即使你用IK把悬空那只脚拉到了坡面脚的朝向仍然是动画原本的朝向。脚掌没有顺着坡面旋转鞋底还是平行于世界地平面的。这个现象在斜坡上尤其扎眼就像一个人穿着硬底皮鞋站在倾斜的台阶上整个鞋底只有边缘一点碰到地面完全不符合物理直觉。高度差好解决Two Bone IK、FABRIK、甚至简单的骨骼位移都能把脚“送”到地面。真正麻烦的是角度差。因为Foot IK的常规做法只处理了Effector Location也就是脚踝或脚的目标位置根本没有处理脚骨的旋转。要让脚掌和地面贴合必须额外把地面法线转换成脚骨的旋转再叠加到动画上。1.2 先分清“查询”和“物理模拟”别把路带偏很多刚开始做Foot IK的人会在网上搜到两种完全不同的方向一种是动画蓝图里的Line Trace加Two Bone IK另一种是给脚部骨骼开Simulate Physics让它自己掉下去碰地面。这两条路的哲学完全不同。Line Trace属于碰撞查询Query。它只回答一个问题从A点向B点发出的射线有没有碰到东西碰到的点在哪碰到的面法线是什么这个过程不做物理计算不改变角色速度不产生冲量。Foot IK用查询就足够了我要的只是“脚底下面有多高、坡面朝哪个方向”。而物理模拟Simulation是另一套体系。开启Simulate Physics后骨骼受重力、惯性、碰撞、约束影响脚会真的“掉”到地面上看起来好像更自然但它会和动画系统抢控制权脚会抖动、会穿模、会和动画手势互相拧巴。简单说查询是采样世界模拟是反馈世界。Foot IK应该用查询不是模拟。后面我会再展开讲这个分界线。1.3 为什么选Two Bone IK而不是FABRIK或CCDUE4自带的IK节点里能用于腿部的主要是Two Bone IK、FABRIK、CCD。我的选择是Two Bone IK因为它和腿部结构完全吻合大腿、小腿、脚正好是三段式骨骼链。Two Bone IK会根据Effector位置反推大腿和小腿的旋转并且带有Twist控制不容易出现膝盖乱转的“面条腿”。FABRIK适合多关节链比如脊椎、手臂迭代解算会平滑收敛但用在腿上略显大材小用。CCD适合过约束的链用在两条腿后会不稳定。另外UE4的老项目里Two Bone IK节点稳定、参数直观、网上资料多出了问题也容易查。所以除非你的腿骨结构特殊否则首选就是它。2. 动手前的准备碰撞查询、骨骼与参数2.1 射线往哪打怎么打决定一半的稳定性我这里说的实现方式非常常见左脚和右脚各发一条射线从脚踝或脚骨Socket位置向下打。射线起点用脚部Socket终点是起点往下减去一个固定距离这个距离叫Reach Distance。具体在蓝图里这样接Event Blueprint Update Animation - TryGetPawnOwner - IsValid拿到Pawn后用GetSocketLocation读取脚部Socket的世界坐标然后发Line Trace。Trace Channel可以选Visibility也可以选WorldStatic看项目碰撞预设。关键是Actors to Ignore里一定要把自己加进去否则射线可能先打中角色的Capsule顶到自身上导致IK目标悬浮在半空。射线命中后要同时拿两个值Hit Location和Hit Normal。Hit Location用来算脚的目标位置Hit Normal用来算脚的目标旋转。很多人只拿位置不拿法线这就是为什么脚能贴地却不旋转。2.2 核心参数表建议直接抄走参数这个东西网上教程给的数值往往来自他们的项目直接照搬不一定合适。我给一组我常用的初始值你用这套值起步再按角色体型调。参数建议初始值作用ReachDistance80~120射线向下探测长度。太短斜坡低处打不到太长高处会吸地FootHeight5~10脚骨骼离鞋底的高度。为0时脚骨会陷地需要按模型微调InterpSpeed10~20位置和旋转插值速度。越大越灵敏越小越平滑MinNormalZ0.3法线Z值低于这个阈值就忽略防止射线打到台阶立面或墙面这里特别说一下FootHeight。射线打到的命中点是坡面而坡面是鞋底接触的地方不是脚骨骼所在位置。如果直接把Hit Location当Effector脚骨会插进地面一小截。正确做法是让目标点沿法线方向抬升一个FootHeight让鞋底自然踩在坡面上。这个值一般是脚踝骨骼到脚底的距离我习惯先设8厘米再进游戏微调。2.3 为什么要用IK Alpha曲线而不是全程开启如果两条射线每帧都在算且IK权重恒为1那么角色走路时脚在摆荡相也会被强行拽向地面看起来就像脚底装了磁铁每个脚步都拖着地面滑过去。这个问题不是IK逻辑错了是权重没控制好。我习惯在混合空间里加一条EnableFootIK动画曲线。这个曲线的值在支撑相为1在脚离开地面的摆荡相为0。动画蓝图里用GetCurveValue读出来作为IK的目标Alpha再经过FInterpTo做平滑过渡。这样脚在离地时保持原始动画脚踩到地面时才开始发力过渡自然不会突然瞬间切换。3. 动画蓝图核心链路Two Bone IK 地面法线旋转3.1 Event Graph每帧算左脚和右脚的目标我这里以第三人称角色为例角色有左脚、右脚两个Socket在Event Graph里分别处理然后存成变量给动画图用。伪代码逻辑是这样的if (LineTrace_Left.Hit): L_FootLocation Hit.Location Hit.Normal * FootHeight L_FootAlphaTarget 1.0 else: L_FootAlphaTarget 0.0 L_FootAlpha FInterpTo(L_FootAlpha, L_FootAlphaTarget, DeltaSeconds, InterpSpeed)右侧重复一遍。需要注意的是L_FootAlphaTarget是每帧直接置0或置1的但L_FootAlpha要经过插值不能直接使用目标值。否则脚会在落地瞬间“啪”一下贴上去离地瞬间又“啪”一下弹开非常生硬。位置算出来后先存成L_FootLocation变量。同时把Hit Normal也存下来下一步算旋转要用。3.2 AnimGraph里Two Bone IK怎么接动画图里节点的串联顺序我固定是这样Final Animation Pose - Two Bone IK (Left) - Two Bone IK (Right) - Modify Bone (Left) - Modify Bone (Right) - Output Pose每个Two Bone IK重点设置这几个属性IK Bone填foot_l或foot_r这是要解算的末端骨骼。Effector Location Space选World Space或Component Space我习惯用World Space直接填射线算出来的世界坐标。Effector Location连到事件图存下来的L_FootLocation变量。Joint Target Location也很重要它告诉IK膝盖应该朝哪个方向弯。如果不填Two Bone IK有可能解出内八字、膝盖外翻等各种奇怪姿势。我把膝盖Socket的位置加上角色前方向量乘以固定距离作为Joint Target。这个值不需要每帧更新角色初始化时算一次就行。Alpha连L_FootAlpha。这一步解决的是高度差让脚能准确踩到坡面。3.3 地面法线转成脚骨旋转这是核心中的核心Two Bone IK管位置不管脚底朝向。所以要在它后面加一个Modify Bone节点把脚骨旋转按地面法线叠加上去。法线是世界坐标里的方向我需要先转换到Mesh组件空间。因为Modify Bone节点里的Component Space是相对于Mesh组件的。不转换的话如果角色旋转了90度左右脚的法线旋转结果会对不上。转换方式是用Mesh组件的InverseTransformDirection节点处理Hit Normal。得到组件空间法线后再用下面两个角度算出旋转Pitch atan2(Normal.X, Normal.Z) Roll -atan2(Normal.Y, Normal.Z) SlopeRotator MakeRotator(Pitch, 0, Roll)Pitch管前后坡Roll管左右坡。如果项目里角色前方向不是X轴或者左右手坐标系导致结果反了直接调正负号就行不用死记。我这里解释一下为什么要用反正切当平面法线和Z轴重合时角度是0当法线倾斜X或Y分量变大反正切能准确还原出坡面相对垂直方向的角度。直接用MakeRotFromZ(Normal)也不是不行但最终旋转会包含角色自身朝向容易和动画产生“拧麻花”效果。最后在Modify Bone里这样设置BoneToModify填foot_lRotation Space选Component SpaceRotation Mode选AdditiveRotation连L_FootSlopeRotAlpha连L_FootAlpha。Translation和Scale都设成Ignore。这里用Additive加法模式而不是Replace替换模式是为了保留动画原有的脚踝弯折只在这个基础上补一个坡面角度。如果直接用Replace站在斜坡上脚确实贴地了但待机动画里脚踝的微调也会被抹掉角色会显得僵硬。3.4 骨盆高度要不要一起调如果你的地形只是普通缓坡只调脚就够了。但如果角色要上下楼梯、踩大块石头只有脚贴地会导致膝盖过度拉伸或者角色好像“劈叉”。这时候可以考虑给骨盆也做一点修正。最简单的做法是对比左右脚的IK偏移差值得到一个骨盆的垂直和旋转修正量再修改骨盆骨骼的位置或旋转。不过骨盆修正很容易做过头让角色看起来像在坐电梯。我的经验是先把脚部IK调稳定再按需加骨盆修正而且骨盆的InterpSpeed要比脚部更慢宁可迟钝不能抖动。标题里提到的问题大部分情况下不需要骨盆也解决得好。4. 常见问题与排查记录4.1 脚在斜坡上还是“平的”这个是最常见的问题。先检查你是不是只把位置加上了法线偏移整个链路里却没有修改脚骨的旋转。如果位置IK和旋转IK都做了再检查Modify Bone的Rotation Mode。注意不能把旋转加到脚踝甚至小腿上那样脚掌不会转。BoneToModify一定要是脚骨。还有一个容易漏掉的地方Modify Bone节点的Alpha也要接IK权重。如果只给Two Bone IK接了AlphaModify Bone那边权重为1结果就是位置平滑过渡了旋转却还是瞬间跳变看起来像脚崴了一下。4.2 脚在台阶边缘疯狂抖动射线打到台阶立面时Hit Normal接近水平算出来的Pitch或Roll会特别夸张脚就像踩在刀刃上一样来回摆。解决办法是判断Hit Normal.Z低于阈值就直接忽略这一针的命中。我一般设0.3也就是坡面超过70度左右就不处理。普通台阶和斜坡的命中点法线Z都远大于0.3不会影响效果。如果抖动发生在平地上检查L_FootAlpha的插值速度。插值速度太快IK位置每一帧都在追赶地面会有些微抖动太慢又显得脚跟不上地形。我一般从10开始一边跑斜坡一边调直到肉眼看不到明显颤动。4.3 走路时脚像“吸”在地上这是典型的IK权重全程为1的问题。看角色走路时摆荡的那只脚如果不离开地面那就是Alpha曲线没起作用。去混合空间里确认EnableFootIK曲线是否在正确的动画片段的正确时间帧赋值。也可以先不管曲线直接用动画片段的播放进度做近似权重但精确控制还是曲线最可靠。另外射线长度太长也会加剧这个问题。角色从高处跳下来离地30厘米射线还能打到下面50厘米的地面IK就会把脚提前拽下去。ReachDistance给100合适不要给几千几万。4.4 膝盖反拐、姿势拧巴膝盖乱转先查Joint Target。Joint Target不是随便设一个点就完事它要尽量放在膝盖前方也就是角色前方向量与膝盖位置交叉的位置。如果Athlete模型是X轴朝前就用膝盖Socket位置 ActorForwardVector * 30。如果是右脚可以把前方向量稍微偏外一点但先不要偏大多数角色默认就够。4.5 查询和物理模拟的坑我再强调一次有次调试脚面在碰撞体上不停弹跳检查半天发现是某个人为了“脚能踩着箱子”给脚骨开了Simulate Physics。Foot IK查询已经把脚放到箱子上Simulate Physics又在同一帧里让脚骨受重力往下掉两个系统互相打架结果就是高频抖动。记住分界线查询负责采样世界模拟负责表现物理反馈。要做脚踩石头联动石头的效果单独加物理约束和冲量传递就行不要和Foot IK混在一起。5. 还想再抠细节输入映射、物理模拟与调试材质5.1 外接设备映射先于动画别让输入绑架IK有些项目会接方向盘、摇杆、跑步机甚至体感设备。我的建议是无论什么外接设备映射到角色状态时都只做一层转换设备输入 → 目标速度/转向 → 角色移动组件 → 混合空间动画 → Foot IK。不要让设备的原始轴向直接驱动脚骨旋转。Foot IK只关心地面贴合不应该关心输入来源。如果硬要把外接设备的位移映射到角色上正确的做法是在Pawn层面把设备数据转换成加速和转向指令让CharacterMovement自己处理Foot IK照常在动画层工作。这样以后换设备、换输入协议都不用重写IK逻辑。5.2 查询和物理模拟器的边界画画线就清楚做一个简单的测试就能理解在斜坡上开DrawDebugLine显示Foot IK的射线。查询模式下射线是一条从脚向下的虚线命中后出现一个Debug点角色位置不会被改变。模拟模式下射线还没出来脚已经开始往下掉角色重心也会受到影响。调Foot IK时我希望射线稳定、目标明确不希望角色重心被脚一下一下地顶起来。所以我把Foot IK严格限定在查询侧物理模拟留给跳跃、被撞飞、尸体倒地这些场景。5.3 用调试节点和材质观察地面信息调试时我必开DrawDebugLine和DrawDebugSphere用彩色线条把射线、命中点、目标点都画出来。命中点位置正常说明位置IK没问题再开DrawDebugCoordinateSystem在命中点显示法线坐标轴法线垂直坡面说明旋转计算的数据源没问题。有些项目还想做脚印、泥地痕迹。这个时候可以用SpawnDecalAtLocation生成贴花材质节点里配合世界坐标、法线方向、透明度节点做脚印渐隐。但要注意贴花和材质是表现层不应该反过来影响Foot IK的计算结果。调试时先把表现层关掉只看射线和目标点逻辑稳定后再开贴花效果能省很多排查时间。最后再分享一个习惯做Foot IK不要迷恋参数要做减法。先把位置IK调稳定再加旋转IK最后才考虑骨盆和贴花。每次只引入一个变量出问题就知道是哪一层。我在实际项目里踩过几次坑之后现在只要发现脚部异常第一步永远是关掉表现层、打开DrawDebugLine沿着斜坡跑两圈基本就能定位是射线起点问题、法线转换问题还是权重插值问题。