Unityのラグドールを使ったダウンアニメーション後の起き上り機能を作成する

今回はUnityのラグドール機能を使って銃などのダメージを受けてバタッと倒れたキャラクターがアニメーターコントローラーの制御に戻って立ち上がる機能を作成したいと思います。

前の記事でラグドールを使ったヒットリアクション機能を作成しましたが、そちらで作成した敵の移動機能やスクリプトの処理も使っているのでそちらの記事も参照してください。

Unityのラグドールを使ったヒットリアクションの作成
Unityのラグドールを使って銃でダメージを受けた時の敵のダメージアクション機能を作成していきます。

今回の機能を作成すると以下のようなものが出来上がります。

上の動画ではダメージを受けたら即座にラグドールを使ってダウンしていますが、ヒットリアクションと組み合わせた機能は最後の方で紹介します。

スポンサーリンク

ラグドールでダウン後の起き上り機能の概要

ラグドールを使ったダウンのアニメーションは攻撃を与えた時にその部位のコライダに力を加え、CharacterControllerやAnimatorコンポーネントを無効化し、ラグドールの機能だけで倒れるようにします。

起き上りの機能はラグドールで倒れたキャラクターがどの向きを向いているかを調べ、その状態に近いアニメーションを再生させることで実現させることにします。

ただ、ラグドールでダウンしたキャラクターの位置や角度はダウンする前の位置や角度から動いたり、ダウン後のキャラクターとAnimatorControllerで設定しているアニメーションの位置と角度が合いません。

つまり、単純にCharacterControllerとAnimatorを再度有効にするだけでは実現出来ません。

なのでラグドールでダウンしたキャラクターの両足の位置の間の位置の計算とキャラクターが倒れた方向からキャラクターの角度を計算し、AnimatorControllerの制御に戻す前に位置と角度を変更しておきます。

細かい処理はスクリプトの解説部分を見て頂くとわかると思います。

敵キャラクターにラグドールを取り付ける

敵キャラクターにはCharacterControllerの取り付けとコライダの設定がされており、ラグドールが取り付けられている必要があります。

Unityのラグドールを使ったヒットリアクションの作成
Unityのラグドールを使って銃でダメージを受けた時の敵のダメージアクション機能を作成していきます。

の記事を参照して設定してください。

ダウン後の立ち上がりアニメーション

ダウン後の立ち上がりアニメーションは各自用意してください。(^_^;)

ヒットリアクション機能で参考にした方のプロジェクトで使用していたアニメーションは著作権がどうなっているのかわからないので、そちらは使わずわたくしは自作しました。

キャラクターの基点は足元にして作成し、

アニメーションはキャラクターのダウン後の状態と立ち上がった状態を回転して作り、その間のフレームを手と足のIKを動かして立ち上がるようなアニメーションに仕上げました。

うつ伏せからの立ち上がりアニメーション

上はうつ伏せからの立ち上がりアニメーションですが、その他横向きからの立ち上がりアニメーション、仰向けからの立ち上がりアニメーションを作成しておきます。

横向きからの立ち上がりアニメーションは左右の違いはUnityのMirrorで対応するので左向きか右向きかのアニメーションをひとつだけ作ります。

どのアニメーションでも同じ方向を向いて立ち上がるようにしておきます。

Unityでのアニメーションの設定

作成したアニメーションをUnityに取り込み、Animation TypeをHumanoid型にしたらアニメーションの設定を行います。

以下はGetUpFromBackアニメーションの設定です。

Unityでの立ち上がりアニメーションの設定

Root Transform RotationとRoot Transform Position(Y)はBake Into Poseにチェックを入れ、Based UponはOriginalにし、Root Transform Position(XZ)はBake Into Poseのチェックを外し、Based UponはCenter Of Massにします。

Root Transform Position(XZ)のBake Into Poseのチェックを外しているのは立ち上がりアニメーション後にスーッと元のキャラクターの位置に戻るのを避ける為です。

Based UponをOriginalにして足元を基点にするとスクリプトの記述が楽になるのですが、これだとラグドールからAnimatorControllerを制御を移す時の回転のズレが大きくなる為Center Of Massにしています。

アニメーションの作り方やUnityでのアニメーションの設定によってはスクリプトの処理を変える必要があったり、処理がうまくいかないこともあります。

アニメーションクリップの設定に関しては

UnityのAnimationClipのルートモーションの設定
UnityのAnimationClipのルートモーションの設定等をみていきます。

や、Unityマニュアルの

Animation タブ - Unity マニュアル
アニメーションクリップ は、Unity のアニメーションの構成要素です。それらは、RunLeft、Jump、Crawl などの独立したモーションを表し、様々な方法で操作し組み合わせることで、活気のあるアニメーションを生み出すことができます (アニメーションステートマシン、アニメーターコントローラー 、ブレンドツリー を...
ルートモーションの仕組み - Unity マニュアル
キャラクターの重心が Body Transform に該当します。これは Mecanim のリターゲティングエンジンに使用され、最も安定した Displacement モデルを提供します。ボディの向きはアバターの T ポーズに対して相対的に、下半身と上半身のボディの向きの平均を使います。

も参照してみてください。

AnimatorControllerの状態と遷移の作成

敵のAnimatorに設定するAnimatorControllerの状態と遷移は以下のように作ります。

ラグドールダウンからの立ち上がり機能のアニメーターコントローラー

アニメーションパラメータ―はfloat型のSpeed、Trigger型のGetUpFromBack、GetUpFromProne、GetUpFromLeftSide、GetUpFromRightを作ります。

GetUpFromBackは仰向け立ち上がり、GetUpFromProneはうつ伏せからの立ち上がり、GetUpFromLeftSideは右側で横たわり左側に立ち上がり、GetUpFromRightは左側に横たわり右側に立ち上がりの条件です。

Idle→WalkはSpeedが0.1以上、Walk→IdleはSpeedが0.1以下
IdleやWalkから対応するアニメーションパラメータ―がトリガーされたら遷移し、それぞれの状態からIdleへと遷移します。

Idleへと遷移する時の条件はHas Exit Timeにチェックを入れ、時間が経過したらIdleへと遷移するようにします。

例えばGetUpFromBack→Idleのインスペクタは以下のようになります。

GetUpFromBack→Idleへの遷移条件

スクリプトの作成

スクリプトを作成していきます。

敵の移動スクリプト

敵の移動スクリプトを作成します。

移動処理に関してはヒットアクション機能の時と変わらないので説明を省きます。

Hpプロパティを用意します。

GetUpスクリプトが立ち上がり機能のスクリプトでIsDamageプロパティでダメージ状態がどうかを判定し、ダメージを受けていなければ移動させています。

立ち上がり機能のスクリプト作成

立ち上がり機能のスクリプトGetUpを作成し、敵に取り付けます。

ラグドール機能でダウンしてから立ち上がる機能のスクリプトを作成していきますが、ヒットリアクション機能のHitReactionスクリプトと同じ部分の説明は排除しています。

フィールド宣言とStartメソッド

まずはフィールド宣言部分とStartメソッドを見ていきます。

RagdollStateにGetUpとRagdollを追加します。

IsRagdollプロパティは現在ラグドールで倒れている状態かどうかを表します。

ラグドールでダウンする時はダメージを与えないようにする為、プロパティで確認出来るようにしています。

rayPositionは倒れたキャラクターの向いている方向を確認する為のレイを飛ばす位置を設定します。

今回の場合はゾンビのBip01 Pelvisというボーンを設定します。

lengthOfFrontAndBackRayはレイを飛ばす位置から前後に飛ばすレイの長さを設定します。

これはうつ伏せか仰向けに倒れたかどうかを確認する為に腰(Bip01 Pelvis)の位置から前後にレイを飛ばしますが、そのレイの長さです。

lengthOfLeftAndRightRayはレイを飛ばす位置から左右に飛ばすレイの長さを設定します。

これは横向きに倒れたかどうかを確認する為に腰(Bip01 Pelvis)の位置から横にレイを飛ばしますが、そのレイの長さです。

timeToGetUpはラグドール状態になってからAnimatorControllerの制御に戻すまでの時間を設定します。

Updateメソッド

Updateメソッドではキャラクターの状態に応じた処理をしています。

RagdollState.GetUp状態の時にAnimatorControllerの状態がIdle状態になったらragdollStateをRagdollState.Animatedに変更しAnimatorControllerで制御している状態とします。

ラグドール状態から立ち上がり状態へと変更するメソッドの作成

ラグドール状態から立ち上がり状態へと変更するメソッドを作成します。

ChangeToGetUpメソッドはラグドールからAnimatorControllerでの制御に戻す時に呼ぶので、最初にSetKinematicメソッドを呼んでラグドールを無効にし、CharacterController、Animatorを有効にして通常の制御に戻します。

Animatorの右足と左足のボーンを足して0.5を掛けてその間の位置を計算し、averageFootPosに入れます。

足の間の1m上から足の間の1m下までレイを飛ばし、Fieldレイヤーを設定した地面にぶつかった位置の情報をhitに入れます。

ここで、地面にするゲームオブジェクトにはFieldレイヤーが設定されている必要があります。

キャラクターのアニメーションの設定でRoot Transform Position(XZ)をCenter Of Massにして基点をBip01 Pelvisのボーン(中心)にしたのでその為の調整をします。

Humanoid型のSpineに設定しているBip01 Spineボーン(わたくしの場合はBip01 Pelvisを設定してしまいましたが)の位置から足の間の位置を引いたベクトルを計算します。

キャラクターの位置をhit.point(足の間の地面の位置)にオフセット位置を足した位置にします。

Root Transform Position(XZ)をOriginalにしていた場合はhit.pointのままでいけると思います(アニメーションの作りによりけり)。

ここで位置を変更しているのは、ラグドールで飛ばされたキャラクターと、ラグドールになる前のキャラクターの位置を合わせる為です。

次にキャラクターがラグドールで倒れた後の体の向きに応じてAnimatorControllerで再生するアニメーションを変更する処理です。

まずは横向きに倒れたかどうかを判定します。

rayPositionがレイを飛ばす位置でインスペクタで敵(ゾンビ)のBip01 Pelvisのボーンを設定します。

Bip01 Pelvisのボーンのローカルの向きで体の横に向いている矢印の色を確認します。

ゾンビの横の方向の矢印の色

上のようにゾンビのBip01 Pelvisのボーンの横方向は青色の矢印で、これはローカルのZ軸を表しています。

Z軸はtransform.forwardで表せますのでPhysics.Linecastを使てレイの位置からBip01 PelvisボーンのZ軸(transform.forward)の方向にlengthOfLeftAndRightRayの長さのレイを飛ばしFieldレイヤーのゲームオブジェクト(地面)と接触したかどうかを判定します。

この時はキャラクターの左側が地面の方向です。

キャラクターが横向きの時はキャラクターの足元の向きの方向にキャラクターの向きを合わせる為、キャラクターの足元からレイの位置を引いてキャラクターの足元の方向を求め、その方向にキャラクターを向けています。

足の間の位置のYをrayPositionにしているのは高さをレイの位置と合わせる為です。

キャラクターのアニメーションを再生する時はアニメーションパラメータをトリガーするのではなく

と直接AnimatorControllerの状態の指定と再生する位置を指定してアニメーションを再生しています。

これはAnimatorControllerのアニメーションパラメータをトリガーするやり方だと元の状態からGetUpFromRightSideの状態へのブレンドが再生されてしまう為です(うまいやり方があるかもしれませんが)。

なのでanimator.CrossFadeInFixedTimeを使って即座に立ち上がりアニメーションを再生させるようにしています。

AnimatorのCrossFadeInFixedTimeを使うとAnimatorに設定したAnimatorControllerの第1引数で指定した状態の第2引数で指定した秒数の位置からアニメーションを再生してくれます。

キャラクターの右側が地面の時も同じやり方です。

横向きと判定されなかった時はうつ伏せから立ち上がりか仰向けから立ち上がりのアニメーションを再生します。

敵のBip01 Pelvisのボーンの前方は緑矢印でtransform.upで表せるので、レイの位置からtransform.upの方向にlengthOfFrontAndBackRayの長さのレイを飛ばし地面とぶつかるかどうかを調べます。

前方に地面がある場合はうつ伏せで倒れたのでキャラクターの向きは足元の位置からレイを飛ばしている位置の方向に合わせます。

うつ伏せで倒れた時のキャラクターの方向

仰向け(orどの条件も満たさなかった場合)の場合はキャラクターの向きはレイを飛ばしている位置から足元の方向の向きに合わせます。

仰向けで倒れた時のキャラクターの方向

どちらも起き上がった時のキャラクターの方向を計算し、その方向をキャラクターが向くようにしています。

今回はキャラクターのボーンから左右と前後にレイを飛ばして地面に対してどちらを向いているかを計算し、うつ伏せ、仰向け、横向きに応じてキャラクターの向くべき方向を計算しています。

たまにラグドール→AnimatorControllerへのアニメーションの繋がりがおかしい時もあるようなのでここら辺の判別方法はもっと良い方法を探す必要があるかもしれません。

ダメージ処理メソッドの作成

ダメージ処理メソッドTakeDamageメソッドを作成していきます。

ダメージを受けたらChangeToGetUpメソッドをtimeToGetUp秒後に実行するようにします。

ヒットリアクション機能と同時に使う場合は通常のダメージはChangeToBlendメソッドを実行し、敵のHPが10で割り切れる場合はChangeToGetUpメソッドを呼び出すようにします。

SaveBodyTransformとSetKinematicとInitializeRagdollメソッド

Transformの保存メソッドSaveBodyTransform、RigidbodyのIsKinematicの切り替えメソッドSetKinematicとラグドールの初期化メソッドInitializeRagdollメソッドはヒットリアクション機能の時と同じなので説明は省きます。

敵攻撃スクリプト

敵を攻撃するスクリプトを作成します。

マウスの左ボタンを押した位置にカメラからレイを飛ばし、EnemyRagdollレイヤーが設定されたコライダの情報を取得し、GetUpスクリプトのTakeDamageメソッドを呼び出します。

TakeDamageメソッドにはダメージ数とRaycastHit情報を渡します。

これで機能が完成しました。

10ダメージ毎にキャラクターがラグドールの機能でバタッと倒れるようにすると以下のようになります。

終わりに

ラグドールを使ったヒットリアクション機能を作成したのでそれに付随したラグドールで倒れたキャラクターが立ちあがるまでの機能を作成しました。

ラグドール→AnimatorControllerの立ち上がりアニメーションへの遷移はパッと切り替わってしまう感じがしますが、それなりな感じのものは出来たのではないでしょうか。

ラグドールからAnimatorControllerへと切り替える時間timeToGetUpを短くしたり、

ラグドールで倒れる時に加える力を強くして敵が吹っ飛ばされるようにするとうまく動作しない可能性もあります。

そういった不安定な要素を排除したい場合は細かい敵のダメージアニメーションを全部作りAnimatorControllerで全て制御するようにした方がいいかもしれません。(^_^;)

コメント

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