UnityのIKを使ってキャラクターがはしごを登るアニメーションを作る

今回はUnityのIKを使ってアニメーションをスクリプトから操作してみようと思います。

今まではアニメーションクリップを作成し、アニメーターによってアニメーションの遷移を行っていました。

しかし、キャラクターが物を持とうとした時に物のオブジェクトとアニメーションの手の位置がうまく合ってくれなかったりします。

しかしIKを使えば手の位置を物の位置や角度に合わせて調整するという事が出来るようになります。

今回はその機能を使ってキャラクターがはしごを登るようにしてみます。

機能を作成すると、

↑のような感じのものが出来上がります。

IKだけではしごを登っているように見せている為、体が硬い感じですね。

値を調整したりする事でも改善出来るとは思いますが、やはりIKだけだとちょっと難しいですね。

後ははしごを登り切った後のワープが気になる・・・・((+_+))

今回使用するはしごはAsset Storeにある「Free Steel Ladder Pack」を使用させて頂く事にします。

その中のLadderCombinationSampleを使用します。

スポンサーリンク

キャラクターが昇るはしごの設定

はしごの階層

上のようにはしごを設置し、RightHand、LeftHand、RightFoot、LeftFoot、RightKnee、LeftKnee、StartArea、EndArea、WarpPosition、StandPositionを作成します。

HandとFootと名のついたものはここに手と足がくる位置になります。ここを移動させて手と足の位置を動かしていきます。

Kneeは膝の向ける方向を指定します。

StartAreaは、はしごに登るのを開始する検知エリアです。EndAreaははしごを登りきったのを検知するエリアです。
StandPositionははしごに登るのを開始するキャラクターの位置を指定するものです。
WarpPositionははしごを登りきった時にキャラクターを移動する場所です。登りきった後に地面がある所に移動させないと重力で落下してしまう為に用意してあります。

はしご2

はしごは上の画像のような感じです。

これから作成するスクリプトははしごの大きさによってパラメータを変更する必要があります。しかもかなり細かく・・・(^_^;)

ただ一度作ってしまえばそのはしごをプレハブ化して使い回しがききますので、安心してください(はいてますよ)。

はしごのScaleの調整

まずは梯子の大きさを変更します。

はしごのScaleと角度の変更

Scaleを↑のように変更し、Y軸で180度回転しておきます。

回転はカメラの向きにはしごを登らせる為に回転しただけです。

ただここではしごの親元を回転したことで、子要素のRightHand、LeftHand、RightFoot、LeftFootのY軸の角度も180にします。

さらにRightHandとLeftHandのX軸の角度を320にして、手の角度が梯子の持つ部分に合うように角度を設定します(実行しながら目的の角度を探します)。

右手のX軸の角度を変更

StandPositionは

StandPositionの位置

↑のような位置に調整しました。

StartAreaの検知エリアを作っていきます。BoxColliderを追加してください。

はしご3

上のように小さいエリアにしておきます。

なぜなら敵に追われている時に誤ってエリア内に入ってはしごを登らせない為です。

キャラクターを検知したらはしごを登る準備をするスクリプトClimbTheLadder

StartAreaにClimbTheLadderという新しいスクリプトを作成します。

インスペクタで右手や左手等のTransformを設定出来るようにします。

キャラクター操作スクリプトがStairCharaスクリプトになります。

またはしごを昇る時の最初の右手、左手、右足、左足の位置、右ひざ、左ひざの方向を数値で指定し、rightHandBase等に保持しておきます(実行しながら位置を調整してください)。

一度はしごを使ってrighHandやleftHandを移動してしまうと、2度目にはしごを登ろうとした時にrightHandやleftHandが移動した位置から開始してしまう為、元の位置に戻す時に使用します。

OnTriggerEnterメソッドではPlayerタグを設定したキャラクターが侵入した時にキャラクターの状態がはしごを登っているか通常の時かで処理を分けています。

StairCharaスクリプトのSetStairsメソッドではしごを登る準備をさせ、ResetStairsで通常の状態に戻す処理をします。

自身のスクリプトのResetStairsメソッドではRightHand等を元の位置に戻す処理をしています。

その他Getterメソッドを用意しています。

キャラクター操作スクリプトStairCharaスクリプトの作成

キャラクターにはCharacterControllerコンポーネントとAnimatorが設定されている事、AnimatorControllerにはIdle状態Walk状態が作成されている事と、登っている時用に状態を作成する時はbool型のStairsアニメーションパラメータを作成し、Stairs状態に遷移出来るようにしておきます。

それではキャラクター操作スクリプトStairCharaスクリプトを作成していきます。

宣言部とStartメソッド

まずは宣言部とStartメソッドです。

climbLadderSpeedRatioははしごを登る時のスピードの比率で数値を上げるとはしごを登るスピードが速くなります。

isStairsは階段を上っているかどうかのフラグです。

stateで判断出来るのであえてisStairsを用意する必要もないんですが・・・・。

leftHandPosやrightHandPos等はIKの到達点を一旦記憶しておく為に使用します。

Updateメソッド

ではここからがメインの処理になります。

まずははしごを昇る状態になった時(stateがState.stairs)に関数OnAnimatorIK内で右手、左手、右足、左足のIKのウエイトを1にする必要があります。
IKのウエイトが1になると位置を指定すればアニメーション本体とは関係なくそこに右手や左手がそこに移動するようになります。

また位置だけでなく角度も変更が出来ますので、まずはその処理を記述します。
OnAnimatorIK内に以下の記述を足します。
OnAnimatorIK関数がない場合は足すのと、アニメーターコントローラのレイヤーでIK Passのチェックを入れる必要があります。

キャラクターがNormal状態の時は通常の移動処理です。

Stairs状態の時はZ軸座標の動きだけをvelocity(速度)に足していく事にします。

nowPosはキャラクターの位置と元々の位置とのY座標の差を入れます。

その差によってRightHandやLeftHandの位置を変更していきます。

設定する数値は実行しながら値を変更し、細かく設定していく必要があります。

最初の位置はClimbTheLadderスクリプトが保持しているベースの値を設定し、そこから上に昇っていくにつれて値を変更しています。

膝の位置はキャラクターが上に登っていくのと共に上げていけばいいだけです。

はしごの上り下りをしている時は重力を働かせたくない為、State.Stairs以外の時だけ重力値をvelocityに加えています。

手や足の位置を設定する処理部分

次にUpdateメソッドで移動させたRightHandやLeftHandの位置に手や足の位置を持っていく処理部分を記述します。

AnimatorControllerのLayersの歯車をクリックしIK Passにチェックを入れるとOnAnimatorIKメソッドが呼ばれるようになります。

isStairsがtrueの時にIKのウエイトを設定し、位置や角度がrightHandTraやleftHandTraの位置や角度となるようにします。

その他の処理

その他の状態変更メソッド等を作成します。

SetStairsメソッドはClimbTheLadderスクリプトから呼び出されるメソッドでキャラクター操作スクリプト側で右手や左手のTransformを操作する為にTransformを取得しています。

EndAreaの作成

EndAreaはキャラクターがはしごを登り切ったとする範囲です。

Box Colliderを取り付けIs Triggerにチェックを入れます。

EndAreaのインスペクタ

EndAreaにはStopClimbingスクリプトを作成し取り付けます。

キャラクターが検知エリアに侵入したらキャラクターを通常状態にし、warpPositionの位置に移動させます。

warpPositionははしごを登り切った後の地面がある部分に移動させておきます。

EndAreaの範囲

これではしごを昇っている状態の時だけ↑↓のキーだけに反応して動くキャラクターになります。

はしご4

上のようになりました。

細かく調整はしていないので近くで見るとはしごに手足が食い込んでいる可能性もあります。(^_^;)

手足の移動をなめらかにする処理

はしごを登る時に一定の範囲に来たらすぐに目的の位置へ手や足を移動させていますが、
目的の位置まで滑らかにアニメーションしたい方もいると思います。

その為の処理をStairCharaスクリプトに追加します。

まずは宣言部です。

stairSmoothFlagはスムーズに手や足の位置を変更させるかどうかで、stairSmoothValueはスムーズ値です。

次にUpdateメソッドに滑らかに移動する為の処理に改造します。

膝の向きを設定する処理の上のRightHandTra等のローカル位置を変更している部分を変更します。

↑のような感じでスムーズ処理をするかしないかで処理を分けます。

処理が完成したので、インスペクタでstairSmoothFlagのチェックを入れ、stairSmoothValueに値(今回は8を設定)を設定してください。

Unityの実行ボタンを押して確認してみましょう。

はしご5

一気に駆け上がろうとすると目的地に手や足が来る前に次の目的地が設定されてしまう為動きがぎこちない感じになってます。

Y座標の移動値を少なくしたり、stairSmoothValueの値を大きくするとぎこちなさは取れます。
もっといい方法はないもんですかねぇ・・・・

スムーズにやらない方がよく見えるような気もします・・・・(^_^;)

終わりに

IKを使って簡易的にはしごを登らせる処理を作りましたが、改良の余地はありそうですね。

キャラクターのはしごを登るアニメーションをちゃんと作っているならターゲットマッチングを使うともっとちゃんとしたのが作れるかも?

スポンサーリンク

記事をシェアして頂ける方はこちら

フォローして頂くとやる気が出ます

コメント

  1. 匿名 より:

    ここってまだJavaScriptですか?
    C#勢なんで今のままだと詰みなんですが…(涙

    • この記事面倒くさい処理だったんで後でやろうと思って忘れてました・・・・・(^_^;)

      ちょっと時間を頂きます・・・・・(-_-)

      C#で書き直しました。

      改善の余地はいろいろありそうですが・・・・(+_+)

      • 匿名 より:

        迅速な対応ありがとうございます!
        さらに丁寧に追加情報も下さり分かりやすかったです。

        自分でも読み替えてやってみようとしましたが、圧倒的実力不足でしたorz

        人生5回目のプログラミング(勉強)挫折を経験するところでしたが、
        おかげさまでまだ続けられそうです(T_T)

        あと、勘違い、かつ細かいかも知れませんがUpdateメソッド内の解説がnowPosではなくnewPosになっているような( ^ω^)・・・

        • プログラミングはやればやるだけ上達するかもしれません(わたくしを除いて)。

          他の方が書いたプログラムも読めるようになってくるとさらに楽しくなってくるかもしれません(わたくしを除いて)。

          記事の文章間違いはブログ初期の頃は結構チェックしてたんですが、書き換えているうちにスクリプトの変数名を変えていたりするので統一性がなくなっております・・・(-_-)