こんにちは。ほげたつ(@HogeTatu)です。
前回に引き続き、Foot IKについて書いていきます。
今回は 立っている場所よりも低い位置に足を着こうとすると浮いてしまう 問題に対する対応です。
LineTrace用のソケットを追加
LineTraceを用いて足と地面との距離を検出するため、スケルタルメッシュにソケットを追加します。
今回はテンプレートでお馴染みのUE4マネキンに対して追加してみます。
- ball_l ボーンに対して LeftFootSocket を追加
- ball_r ボーンに対して RightFootSocket を追加

キャラクターのカプセルコリジョンサイズを変更
キャラクターが重力がある空間に立っている時、全身を覆うカプセルコリジョンの当たり判定結果から立ち位置を決めています。
つまり何もしなければ、カプセルコリジョンが覆っている空間よりも下に足を伸ばすことができません。
これが浮いてしまう問題の原因です。
前回からの引用です。
前回執筆時点ではコリジョンとメッシュの位置関係を可変にするという方針でいましたが、今回はそもそものコリジョンサイズを変更しておくことで対応します。
以下のように、コリジョンサイズを膝丈くらいまでに縮小します。

高さ補正用の関数(UpdateActorLocationZ)を追加
コリジョンサイズを変更したことにより、このままでは膝下が地面にめり込んでしまいます。
そのため、コリジョン下から各足のソケットに対して LineTrace し、アクターの高さを補正してあげます。
この関数は Tick イベント内から毎フレーム呼び出します。
以下に関数の全体図を記しますが、大きな関数なので細かく分けて説明していきます。

変数一覧
使用されている変数を、名前、説明、デフォルト値の順序で記します。
クラスメンバ変数
InterpSinkingDistance |
アクターZ値補正用のめり込み長さ |
0.0 |
ローカル変数
LeftFootSocket |
左足トレース用ソケット名 |
LeftFootSocket |
RightFootSocket |
右足トレース用ソケット名 |
RightFootSocket |
DeltaSeconds_ |
経過時間(引数からノードを繋ぐと煩雑になってしまうため保持) |
0.0 |
CapsuleLowerLocationZ |
カプセルコリジョンの終端位置(Z値が最も小さい位置) |
0.0 |
HitOffset |
トレース処理ヒット時の終端位置からのZ値オフセット |
0.0 |
SinkingDistance |
トレース処理ヒット時のめり込み長さ |
0.0 |
LocationInterpSpeed |
徐々に高さ補正の値を変更するための係数 |
50.0 |
上昇中は更新しない
ジャンプ等で上昇する時には補正は必要ありません。

カプセルコリジョンの終端位置を取得
接地位置検出のための LineTrace は、カプセルコリジョンの終端位置(Z値が最も小さい位置)から開始するため、カプセルコリジョンのワールド座標から半分の高さを引いてローカル変数に保持しておきます。

両足のトレース処理
カプセルコリジョンの終端位置から、各足のソケットに対して LineTrace を実行します。
地面を検出できたら HitOffset(終端位置からのZ値オフセット)、SinkingDistance(めり込み長さ)が取得できるので、よりZ値が低い方(HitOffset が低い方)を採用してめり込み長さを算出します。

TryFootTrace

TraceFromLocation

めり込んだ分の高さを補正
地面にめり込んだ分の高さをアクター位置に足してあげます。
補正値が大きいと画面の切り替わりが大きくて良くないため、FInterpTo で徐々に補正値を変更していきます。
また、カプセルコリジョンサイズを変更した都合上、ジャンプから着地する時に歩きに切り替わらない問題があるので、着地時は SetMovementMode して歩きに変えてあります。

結果


しっかりと高さの補正ができています。
これであとはもう片方の足がめり込んでいる問題を IK で解決できれば問題なさそうです。
ではまた次回。