FPSを作ってみよう8-IKを使って銃に手を合わせる-

前回キャラクター用のアニメーションをblender2.76bで作成し、UnityにFBXファイルのインポートを行いました。

FPSを作ってみよう7-アニメーションの作成とUnityでの取り込み-
FPSゲームに使うアニメーションの作成とUnityでの取り込みまでを行います。アニメーション作成にはblender2.76bを使って作成していきます。

今回はインポートしたアニメーションをアニメーターの状態として追加し、IKを使ってキャラクターの左手の位置を銃の特定の個所に固定するようにします。

IKに関しては

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

を参照してください。

IKに関する記事は他にも書いているので参照してみてください。

blenderで細かく手の位置をつけている場合はIKを使う必要はないですが、IKを使うと本来のアニメーションとは関係なく手や足の位置を指定する事が出来るので、
blenderでは細かい位置を指定出来なかった時や元のアニメーションを少しカスタマイズしたい時に便利です。

スポンサーリンク

キャラクターに銃を持たせる

それではまずキャラクターに銃を持たせましょう。

銃はAsset Storeから探します。
Asset Storeの検索窓でmakarovと入力して出てくる銃をインポートします。

銃をキャラクターの右手の子要素にドラッグ&ドロップ

銃のインポートが終わったら、キャラクターの右手の子要素に銃のプレハブをドラッグ&ドロップします。

そのままのサイズだとキャラクターより大きすぎる

そのままだと銃のサイズが大きすぎてキャラクターの10倍ぐらいになっています。

銃のScaleを小さくする

銃のScaleの値を0.02に設定し、サイズを小さくします。
驚異の縮小率ですね・・・(+_+)

銃の位置と角度を調整し右手に持たせる

銃のサイズが適当な大きさになったら、銃の位置や角度を右手に持っているように調整します。
次に銃を構え終わった時の銃の位置を調べる為の設定をします。

IdleをいったんWaitShotに変更する

MotionをWaitShotにする

銃を構え終わった時に銃が前を向くように調整する為、MusasiAnimatorのIdleのMotionを
rig | WaitShotに変更します。

これでキャラクターを操作していない時はWaitShotアニメーションが再生されるようになるので銃の向きや位置を調整します。

銃を正確な位置に合わすには

Unityでキャラクターに正確に武器を持たせる
Unityでキャラクターの手の位置に正確に武器を持たせるように調整します。なんとなく持たせる位置を設定していた人には朗報かも!?

を参照してください。

銃が真正面を向くようにする

↑の画像のようにScene画面とGame画面を両方見ながら銃が正面を見るように調整します。
これで銃の位置と角度の調整が出来ました。

キャラクターの左手が少し銃から離れていますね、そこで左手の位置をもう少し銃に近づける為IKを使用します。

IKを使用する

アニメーターのIKPassにチェックを入れる

IKを使用するにはAnimatorのBase Layerの歯車をクリックし、IK Passにチェックを入れます。

IK Passにチェックを入れるとOnAnimatorIK関数が呼ばれるようになるので、その関数内でIKの設定をします。

キャラクターの左手の位置を銃の手の位置に合わせるスクリプトHandIKを作成します。

leftHandは左手の位置を置く銃の手の位置を指定します。

OnAnimatorIK関数内でSetIKPositionWeightとSetIKRotationWeightでAvatarIKGoal.LeftHand(左手)のウエイトを1にして完全にIKが働くようにします。

SetIKPositionとSetIKRotationでAvatarIKGoal.LeftHandの位置を変数で指定した位置に移動します。

AvatarIKGoal.(動かす部位)で両手・両足を指定する事が出来そこで設定された部位が第2引数の位置や角度と同じになります。

設定したウエイトが1なので完全に一致します。
ウエイトが低いと完全一致ではなくなります。

ウエイトを段々と値が変わるようにするとIKを無効から有効にしたり無効から有効にする時に一気に手や足の位置や角度が変わるのではなく滑らかに変化させる事も出来ます。
今回は必要ないので常にウエイトは1にしてあります。

HandIKスクリプトのインスペクタでleftHandに左手の位置を指定しますが、まだ銃の左手の位置を作っていないので作ります。

銃の左手の位置を作成する

銃の子要素に右クリック→Create Emptyをして空オブジェクトを作成し、名前をLeftHandPositionとします。
作成出来たらHandIKスクリプトのインスペクタのleftHandにこのLeftHandPositionを設定します。

これで左手のIKが作用するようになります。

手があらぬ方向に曲がってしまっている

Unityの実行ボタンを押して確認してみると、上のように手があらぬ方向に曲がってしまっています。
LeftHandPositionの位置や角度を変更し左手が銃をささえる感じになるようにします。

左手の位置と角度を調整する

調整が終了すると上のように左手の位置が銃に密接するようになりました。

これで銃の設定と銃の左手の位置の設定が出来たのでMusasiAnimatorのIdleを元のHumanoidIdleに戻しておいてください。

両手ともIKを使いUnityのAnimationでアニメーションを作成する

両手のIKを使わない方はスクリプトの変更やゲームオブジェクトの移動等は行わないよう気を付けてください。最後の方まで読み飛ばしていただいても大丈夫です。

さて、ここからは前回言及した両手ともにIKを使いUnityのAnimationを使って通常の銃を持つアニメーションGunIdle、銃を構えるアニメーションWaitShot、
銃を撃つShot(これはご自分で作成して頂きます)を作成していきます。

前回の記事でも言いましたが、あくまでわたくしは左手のIKのみ使用する方法で記事を作成していくので、両手のIKとUnityのAnimationでのやり方は
独自に読み替えや改良をしていく必要が出てくる事を承知しておいてください。

まずは両手にIKが働くようにHandIKを修正します。

これで右手にもIKが働くようになります。

次は銃の子要素に銃の右手の位置をあらわすRightHandPositionを作成します。

また、銃をキャラクターの右手の子要素にしていると銃はキャラクターの右手の位置や角度で移動しますが、右手はIKで銃の子要素のRightHandPositionを見ていくという
循環がおきてしまいおかしな動作になってしまいます。

銃をEthanSpine1の子要素に移動する

その為銃は↑のようにキャラクターのEthan Spine1の子要素に移動させます。

UnityのAnimationでGunIdleアニメーションを作成する

それではUnityのAnimationで通常の銃を持っている状態GunIdleを作成していきます。

Animationに関しては

銃を撃った後の銃のアニメーションをUnityで作成する
Unityのゲームで使用している銃で弾を撃った時に銃のトリガーのアニメーションを作成していきます。

を参照してください。

UnityのメニューからAnimationウインドウを開く

Unityのメニュー→Window→Animationを選択しAnimationウインドウを開きます。

AnimationのCreateボタンを押す

銃を選択した状態でAnimationウインドウのCreateボタンを押します。

Animationファイルを保存する

↑のようにアニメーションを保存する画面が出るのでGunIdleという名前をつけて保存します。

GunIdleアニメーションと銃のアニメーターが作成される

アニメーションを保存するとProjectウインドウのAssetsエリア(デフォルトの保存先にした場合)にさきほど保存したGunIdleアニメーションと銃のアニメーターが作成されます。

また銃のアニメーターは銃のAnimatorコンポーネントで指定されます。
銃のアニメーションはこのアニメーターで制御する事になります。

GunIdleのアニメーションを作成していく

AnimationタブでGunIdleのAdd Propertyボタンを押して銃のTransformのpositionとrotationを追加します。
Unityの実行ボタンを押します。

デフォルトでは銃の位置はSpine1の位置にある

銃の初期位置がEthan Spine1と同じ場所にあるので移動させます。

銃の位置や角度を動かす

赤丸の録画ボタンを押した状態で銃の位置や角度を変更するとタイムラインにキーフレームが打たれます。

銃の位置が決まったら銃の子要素のRightHandPositionとLeftHandPositionの位置や角度も調整しGunIdleのアニメーションにキーフレームが打たれる事を確認します。

フレーム0以外にキーフレームが打たれている場合は削除してください。

銃のTransformで変更箇所が赤くなる

銃を選択している状態だと↑のようにTransformの背景色が通常とは変わります。

Game画面で手と銃が少し見えるぐらいの位置にする

銃の位置と角度を変更し↑のように手と銃が少し見えるぐらいの位置にします。

Scene画面で見た状態

Scene画面を見ると肘のIKを設定していない為腕が縮こまっています。
気になる方はIKHintを使い肘の角度を変更してみてください。

これでGunIdleのアニメーションが出来ました。

UnityのAnimationでWaitShotアニメーションを作成する

次は銃を構えるWaitShotを作成していきます。

新しいAnimationClipを作成する

↑のように新しいアニメーションクリップを作成し名前をWaitShotとします。

両手のIKの位置のプロパティを追加する

GunIdleのキーフレームを選択し、Ctrl+CでコピーしWaitShotのフレーム0を選択してCtrl+Vでペーストします。

さらに銃の子要素であるRightHandPositionとLeftHandPositionのpositionとrotationのプロパティを追加します。

WaitShotのフレームでUnityの実行ボタンを押し、銃を構えている状態に位置と角度を調整します。

Animationの録画ボタンを押してフレーム10の位置で銃とRightHandPosition、LeftHandPositionの位置と角度を変更します。

ここで少し難しいのはフレーム0からの角度の変更値によっては手首がグルグル回ってしまうアニメーションになる事です。

なんとか手首が回らないようにがんばってください(-.-)
360度から0、0から360度と切り替わると回転してしまうのかも?

両手IKで銃を構えるアニメーションを作った結果

↑のように銃を構えた後のアニメーションが出来ました。

これでGunIdleとWaitShotのアニメーションが出来上がりました。

アニメーションの遷移を作成する

最後にアニメーターで状態の遷移を作りGunIdleからWaitShotの流れを確認してみましょう。

銃のアニメーターを選択する

ProjectウインドウのAssetsエリアにある銃のアニメーターを選択します。

銃のアニメーションの遷移を作成する

アニメーションパラメータにBool型のWaitShotを作成し、GunIdle→WaitShot、WaitShot→GunIdleへと遷移を繋げます。
遷移条件はWaitShotがtrue、falseの時に遷移させHas Exit Timeのチェックは外しておきます。

GunIdleからWaitShotへの遷移条件

↑はGunIdleからWaitShotへの遷移条件になります。

MyCharaスクリプトにWaitShotを操作する処理を追加

次にキャラクター操作スクリプトMyChara内でアニメーションパラメータのWaitShotを操作する処理を追加します。

public var gunAnim : Animator;

で銃のアニメータコントローラを設定出来るようにします。

Input.GetButton(“Fire2”)でFire2が押されていたかどうかでアニメーションパラメータのWaitShotを操作します。

デフォルトではFire2はマウスの右クリックが設定されています。

これでマウスの右クリックを押すと銃を構えるようになります。

片手IK、両手IK双方のやり方を終えて

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

両手IKで作成した銃を構えるアニメーションの確認

↑のようにGunIdleからWaitShotへの遷移が出来ました。
ただ銃がブレてしまいます(Ethan Spine1の子要素にあるので相対的に動く)

キャラクターは銃の位置と角度にIKを使い手の位置を合わせているのでこれは元のアニメーションの影響です。

キャラクターのIdleに設定しているアニメーションがHumanoidIdleで常に体が少し揺れています。
銃がブレないようにするにはIdleのアニメーションはEthan Spine1にあたるボーンの部分があまり動いていないものにするといいかもしれません。

これで両手のIKとUnityのAnimation機能で銃を構えるアニメーションが作成出来ました。
銃を撃つアニメーションも同じようにすれば作成出来ます。

さて、これで銃を持つ、銃を構える、銃を撃つアニメーションの作成が完了しました。
現状ではまだアニメーターの設定等(片手IKの場合)を行っていないので次回やりたいと思います。

銃を持ったり、構えたり、撃ったりと言う事は移動時も出来るようにしたいので、アニメーターのレイヤーとアバターの機能を使って部分的にアニメーションをさせ、実現したいと思います。