UnityのIKを使って足の位置と角度を地面に合わせる機能

今回はキャラクターの足の位置と角度を地面に合わせる機能を作ってみたいと思います。

今回

YouTube
YouTube でお気に入りの動画や音楽を楽しみ、オリジナルのコンテンツをアップロードして友だちや家族、世界中の人たちと共有しましょう。

こちらの動画を参考にさせていただきました。

IKに関しては

UnityのIKを使って物を運ぶアニメーション
UnityのIKを使ってキャラクターが物を運んでいるようなアニメーションを作成していきます。

の記事を参考にしてください。

今回の機能を作成すると、

↑のような感じで足を地面の位置と角度に合わせる事が出来ます。

片足が空中にある時は別途なんらかの処理を加える必要がありそうです。

まずは足の位置や角度を地面に合わせるやり方を考えます。

足の位置をアニメーションとは別に地面に合わせる必要があるのでIKの機能を使います。

地面に位置と角度を合わせるので、足が地面と接地している個所を調べる必要があります。
その為にPhysics.Raycastを使ってキャラクターの足から下にレイを飛ばし常に接地面を調べるようにします。

スポンサーリンク

足からレイを飛ばし地面の情報を取得するスクリプト

手のIKを使った時と同じようにキャラクターにレイを飛ばす位置を設定し、そこからレイを飛ばし地面と当たった位置と角度に足のIKを設定します。

ここまでは手のIKの時と同じ事をしています。

足のIKの場合、立っているアニメーションの時はレイの当たった位置にIKのウエイトを1にして位置を設定すればいいんですが、歩いている時や走っている時に常にウエイトを1にしているとヒザ神(ロンドンハーツから引用)のような動きになってしまうのでアニメーションの動きにしたがってウエイトを変更していく必要があります。

この処理は後でやります。

既存のキャラクターに足のIKを施すスクリプトFootIKを新しく作り取りつけます。

スクリプトを少しづつ見ていきます。

useIKは足のIKを使うかどうかで、インスペクタでチェックのオン・オフを出来るようにします。

useIKRotは足の角度を地面に合わせるかどうかです。

rightFootWeightとleftFootWeightは両足のIKのウエイトを入れます。

rightFootPos、leftFootPosは両足の位置、rightFootRot、leftFootRotは両足の角度を入れます。

offsetは足を置く位置のオフ設置値です。

rayRangeは両足から下側にレイを飛ばす距離です。

rayPositionOffsetは足が接地する地面の位置と角度を取得する時にレイを足先から飛ばしますが、その位置の上へのオフセット値を指定します。

これは足先からレイを飛ばすとアニメーションと接地部分の関係から地面の下に足先が来てレイが地面の下から出てしまう現象の対処のために足先より上からレイを飛ばす為の調整値です。

OnAnimatorIKはAnimatorControllerのレイヤーでIK Passにチェックを入れていると呼ばれるメソッドです。

useIKがfalseの時はそれ以降の処理をしないようにreturnします。

両足からレイを下側に飛ばし、地面に接触していたらその位置と角度を保持します。

レイの当たった位置はhit.pointで得られますが、角度は上側の方向と接触面の表面の方向から計算した角度に自身の足の角度をかけて求めます。

得られた情報はそれぞれのフィールドに保持しておきます。

で右足のIKの位置を取得出来ます。

useIKRotがtrueの時だけ足の角度を地面の角度に合わせます。

RightFootWeightとLeftFootWeightはアニメーションカーブの値をそのまま設定します。

アニメーションカーブはこの後作成します。

アニメーションの再生位置によってIKのウエイトを変更する

アニメーションの再生位置でIKのウエイトを変更出来るようにします。

まずは立っている状態のアニメーションIdleの場合は常にウエイトを1にして、レイの当たった位置に足を合わせるようにします。

アニメーションのCurveを使うとアニメーションの状態によってアニメーションパラメータの値を変更出来ます。

またアニメーションパラメータの名前と同じ名前をCurveの名前に指定すれば、アニメーションパラメータの値にCurveの値がそのまま設定されます。

アニメーションカーブに関しては

Unityのキャラクターのアニメーションの動きに応じてコライダのサイズを変更する
Unityで使う当たり判定(コライダ)のサイズをアニメーションに応じて変更し、ジャンプ中のキャラクターのコライダのサイズを変更し狭い空間を通過出来るようにしてみます。

を参考にしてください。

まずはアニメーションパラメータを作成します。

footik5

上のようにRightFootWeightとLeftFootWeightと名前を付けます。

footik3

次にIdleの状態のアニメーションを選択します。

footik4

上がIdleに設定しているアニメーションです。これを選択し、インスペクタ上のCurveを作成します。

footik6

Curvesの+の部分をクリックしRightFootWeightとLeftFootWeightを作成します。
ここでつける名前はアニメーションパラメータと同じ名前にします。

値の部分を1と設定し、常に1になるようにします。
これでIdleのアニメーションのCurveの設定は終了です。

次に走るアニメーションのCurveを設定します。

歩くアニメーションにアニメーションカーブを設定

上のようにアニメーションの動きが見えるようにウインドウを動かしておきます。

Idleのアニメーションの時と同じようにCurveにRightFootWeightとLeftFootWeightというパラメータを作成します。

次に足の着地時はウエイトを1に、離れた時はウエイトを0になるようにCurveのパラメータを変更します。

まずは右足の着地時にRightFootWeightのウエイトを1にします。
アニメーションで右足全体が着地した地点を探します。

footik8

その部分を見つけたら、RightFootWeightのKeyを足すアイコンをクリックし、パラメータを1に設定します。
今回の場合はアニメーションの最初に右足着地しているので、Keyの追加をする必要はないかもしれません。

次に右足が離れる部分までアニメーションを移動します。

footik9

右足が離れる部分でRightFootWeightのKeyを追加し、パラメータを0に設定します。
右足が離れているアニメーションの間はウエイトを0に設定し、着地したら1に設定します。

足が空中にある間から着地までのちょっとの間はウエイトが0から1になめらかに遷移するようにします。
右足の設定が終わったら、左足の設定も同じようにしてください。

設定が終わったらUnityの実行ボタンを押してください。
足のIKがうまくいくか見てみましょう。

footik13

確認の為にIdle状態の時にRunのアニメーションを設定します。(キー操作なくアニメーションの動きを確認する為)
キャラクターをコピーしFootIKをOnにしたキャラクターとOffにしたキャラクターのアニメーションを比較し、本来のアニメーションと差異がないようにCurveのパラメータを設定していく必要があります。

設定が終わったらIdleのアニメーションをIdleに戻し、IKの部分を見ていきましょう。

上記のように足がきっかり着地した時や離れた時ではなく、右足を前に出した後降りてくるあたりでキーを作り、値を1にして、右足が地面を離れる時にキーを打ち値を0、先ほど作った値1のキーの少し前にキーを作り値を0にすると滑らかな感じになるかもしれません。

以下のような感じです。

足のIKのウエイトを滑らかに変えるアニメーションカーブ

出来たと思ったのに足が地面に届かない

footik10

んー、まったく出来ておりません・・・・(+_+)
右足は何となくレイの当たった位置に固定されているようですが、左足がレイの当たった位置に到達しません。

キャラクターを動かすスクリプトをOffにして、
キャラクターを選択し、TransformのYの位置を下げてみます。

footik11

上のように左足もうまく接地しました。

今度は地面をキャラクターを押し上げる感じで下から上に移動させます。

footik12

上のように足の位置が接地し、角度も地面に合っています。

つまり最初の画像ではRayが地面に当たっていてIKの設定もうまくいっているはずなのに、なぜうまく接地しないのかというと体の重心が右足部分を基点にしているから左足は伸ばしているけど地面に到達しない為です。

下から地面を上げた場合は到達点をキャラクターの足によせてるので問題が出ません。

足が地面に到達しないのはコライダの影響かも

足が空中に浮いてしまう場合もあるので、両足の距離を計算しコライダの位置を変更することで対応してみます。

処理を追加していきます。

isChangeColPosはコライダの位置を調整するかどうかの設定です。

distanceは右足と左足の距離の半分を入れます。

defaultCenterはコライダのCenterの位置の初期位置です。

smoothingはコライダの位置を調整する時のスピードです。

OnAnimatorIKメソッド内の最後に処理を追加します。

Math.Roundを使って両足のY軸の位置を小数点以下2桁までに丸めて差の絶対値を計算します。

CharacterControllerのcenterの位置のY軸の位置をデフォルト値からdistanceの値を足して調整します。

これで完成です。

地面となるゲームオブジェクトにはFieldレイヤーを設定し、確認してみてください。

終わりに

これでIKを使って足の位置と角度を地面に合わせる機能が完成しました。

以前は空中に浮いて見えてしまう時に強制で位置を調整してましたがやめました。

今回の修正である程度機能としては出来たのではないかと思います。

タイトルとURLをコピーしました