UE自帶的IK RIG和ControlRig技術
【UE5】角色腳部IK——如何讓腳貼在不同斜度的地面(設置腳的旋轉)_嗶哩嗶哩_bilibili
實驗后這個還是有一部分問題,首先只能保證高度不能穿過,但是腳步旋轉還是會導致穿模
IK前,整個模型在斜坡上會浮空
參考制作:https://www.youtube.com/watch?v=YDTxXM-ss5w
沒有動畫的時候是正常的,有動畫后就又回到原來的樣子
PowerIK
Ground Settings - Power IK
虛幻引擎插件:使用Power IK輕松愉快地實現腳底板位置矯正-CSDN博客
Foot Placement
Skeletal Controls - Foot Placement Node - #2 by High500 - Character & Animation - Epic Developer Community Forums
https://www.youtube.com/watch?v=ENmX4YupJY8
這個方法成功了
參考視頻 https://www.youtube.com/watch?v=BuHhKj71DU0
首先給骨骼建立虛擬骨骼vb_foot_root,vb_foot_l和vb_foot_r
在FootPlacement這里,把VB_foot_root作為IKFoot的Root骨骼,把自己的Foot_r和Foot_L作為FK骨
LegIK這里把VB的IK骨骼加上,FK骨骼和前面一樣
使用了節點之后腳部不會穿過地面了
左邊是沒有使用Foot,右邊是使用Foot
這個方案有一定局限性,需要是根骨骼運動動畫,動畫本身Root位置不能低于地面,不能控制除了Foot骨骼以外的旋轉(例如Ball骨骼穿過地面)
腳底部浮空的問題需要使用IKRIG解決
制作腳底IK檢測地面
在Ball朝下檢測與地面的距離,當和地面的距離在一定范圍就判斷為浮空,把腳IK向下移動
思路是制作IKRig,利用IK帶動骨骼向下移動,同時有逆向運動學,帶動身體其他位置防止腿部拉長
參考IK: https://www.youtube.com/watch?v=-1zBeREIQYc&ab_channel=MullerDigital
這個是中文機翻
【UE5】角色腳部IK——如何讓腳貼在不同斜度的地面(設置腳的旋轉)_嗶哩嗶哩_bilibili
鎖定Pelvis,讓角色不會飄飛
設置大腿被Foot帶動的的彎曲方向
FootIK需要暴露出變量,在動畫藍圖里面使用
//計算腳浮空與踩住地板
void UBlendAnimInstance::HeelFootTrace(FName SocketName,FVector& OutLocation,float& OutHeelDistance)
{ACharacter* Character = Cast<ACharacter>(TryGetPawnOwner());if (!Character){return;}USkeletalMeshComponent* Mesh = Character->GetMesh();if (!Mesh){return;}// 獲取腳部位置(從腳尖往下發射)FVector SocketLocation = Mesh->GetSocketLocation(SocketName);// 設置射線檢測的起始和結束位置FVector Start = SocketLocation; // 腳底位置FVector End = Start - FVector(0, 0, FootOffset); // 向下發射射線(通過偏移量設置長度)UE_LOG(LogTemp, Log, TEXT("%s 足底的射線位置: Start: %s, End: %s"),*SocketName.ToString(), *Start.ToString(), *End.ToString());// 射線檢測FHitResult HitResult;FCollisionQueryParams QueryParams;QueryParams.AddIgnoredActor(Character); // 忽略自己if (GetWorld()->LineTraceSingleByChannel(HitResult, Start, End, ECC_Visibility, QueryParams)){// 射線命中地面FVector ImpactPoint = HitResult.ImpactPoint;// 計算腳部調整距離FVector Correction = SocketLocation - ImpactPoint;UE_LOG(LogTemp, Log, TEXT("%s 足底距離地面的長度 %s"),*SocketName.ToString(), *Correction.ToString());if (Correction.Z >= 0 && Correction.Z <= 8){// 在插值前記錄當前 OutLocation 和 CorrectionUE_LOG(LogTemp, Log, TEXT("[%s] Correction.Z 在 [0, 8] 范圍內: %f"), *SocketName.ToString(), Correction.Z);UE_LOG(LogTemp, Log, TEXT("[%s] 插值前 OutLocation: %s, Correction: %s"), *SocketName.ToString(), *OutLocation.ToString(), *Correction.ToString());// 執行插值OutLocation = FMath::VInterpTo(OutLocation, Correction, GetWorld()->DeltaTimeSeconds, 10.0f);// 記錄插值后的 OutLocationUE_LOG(LogTemp, Log, TEXT("[%s] 插值后 OutLocation: %s"), *SocketName.ToString(), *OutLocation.ToString());// 限制 Z 分量OutLocation.Z = FMath::Clamp(OutLocation.Z, -0.8f, -0.5f);// 記錄限制后的 OutLocation.ZUE_LOG(LogTemp, Log, TEXT("[%s] 限制后 OutLocation.Z: %f"), *SocketName.ToString(), OutLocation.Z);// 也可在此打印最終的腳底高度UE_LOG(LogTemp, Log, TEXT("[%s] 現在的高度 %f"), *SocketName.ToString(), OutLocation.Z);}else{// 如果 Correction.Z 不在 [0, 8] 范圍內,可以在此打印日志幫助定位問題UE_LOG(LogTemp, Warning, TEXT("[%s] Correction.Z = %f 不在 [0, 8] 范圍內,未進行腳部調整"), *SocketName.ToString(), Correction.Z);}}
}
在動畫藍圖內使用這個節點,輸入腳的位置(foot或者ball)作為腳底檢測,然后發射一個向下檢測的射線
把輸出的值再設置到IK上