前回キャラクター用のアニメーションをblender2.76bで作成し、UnityにFBXファイルのインポートを行いました。
今回はインポートしたアニメーションをアニメーターコントローラーの状態として追加し、IKを使ってキャラクターの左手の位置を銃の特定の個所に固定するようにします。
IKに関しては
を参照してください。
IKに関する記事は他にも書いているので参照してみてください。
blenderで細かく手の位置をつけている場合はIKを使う必要はないですが、IKを使うと本来のアニメーションとは関係なく手や足の位置を指定する事が出来るので、
blenderでは細かい位置を指定出来なかった時や元のアニメーションを少しカスタマイズしたい時に便利です。
キャラクターに銃を持たせる
それではまずキャラクターに銃を持たせましょう。
銃はAsset Storeから探します。
Asset Storeの検索窓でmakarovと入力して出てくる銃をインポートします。
銃のインポートが終わったら、キャラクターの右手の子要素に銃のプレハブをドラッグ&ドロップします。
そのままだと銃のサイズが大きすぎてキャラクターの10倍ぐらいになっています。
そこでヒエラルキーに配置する前に銃のモデルのScaleを調整します。
銃のモデルを選択し、Scale Factorの値を0.025に設定し、サイズを小さくします。
驚異の縮小率ですね・・・(+_+)
ヒエラルキーに配置した銃のゲームオブジェクトのScaleを変更するのではなく、銃のモデルのScale Factorを調整しサイズを合わせます。
ヒエラルキーに配置した銃のScaleは1のまま使えるようにします。
銃のサイズが適当な大きさになったら、銃の位置や角度を右手に持っているように調整します。
次に銃を構え終わった時の銃の位置を調べる為の設定をします。
銃を構え終わった時に銃が前を向くように調整する為、MusasiAnimatorのIdleのMotionを
rig | WaitShotに変更します。
これでキャラクターを操作していない時はWaitShotアニメーションが再生されるようになるので銃の向きや位置を調整します。
銃を正確な位置に合わすには
を参照してください。
↑の画像のようにScene画面とGame画面を両方見ながら銃が正面を見るように調整します。
これで銃の位置と角度の調整が出来ました。
キャラクターの左手が少し銃から離れていますね、そこで左手の位置をもう少し銃に近づける為IKを使用します。
IKを使用する
IKを使用するにはAnimatorのBase Layerの歯車をクリックし、IK Passにチェックを入れます。
IK Passにチェックを入れるとOnAnimatorIK関数が呼ばれるようになるので、その関数内でIKの設定をします。
キャラクターの左手の位置を銃の手の位置に合わせるスクリプトHandIKを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | using UnityEngine; using System.Collections; public class HandIK : MonoBehaviour { // 左手の位置 [SerializeField] private Transform leftHand; private Animator animator; void Start () { animator = GetComponent<Animator>(); } void OnAnimatorIK() { // キャラクターの左手の位置と角度を合わせる animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1); animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1); animator.SetIKPosition(AvatarIKGoal.LeftHand, leftHand.position); animator.SetIKRotation(AvatarIKGoal.LeftHand, leftHand.rotation); } } |
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を修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | using UnityEngine; using System.Collections; public class HandIK : MonoBehaviour { // 右手の位置 [SerializeField] private Transform rightHand; // 左手の位置 [SerializeField] private Transform leftHand; private Animator animator; void Start () { animator = GetComponent<Animator>(); } void OnAnimatorIK() { // キャラクターの左手、右手の位置と角度を合わせる animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1); animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 1); animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1); animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1); animator.SetIKPosition(AvatarIKGoal.RightHand, rightHand.position); animator.SetIKRotation(AvatarIKGoal.RightHand, rightHand.rotation); animator.SetIKPosition(AvatarIKGoal.LeftHand, leftHand.position); animator.SetIKRotation(AvatarIKGoal.LeftHand, leftHand.rotation); } } |
これで右手にもIKが働くようになります。
次は銃の子要素に銃の右手の位置をあらわすRightHandPositionを作成します。
また、銃をキャラクターの右手の子要素にしていると銃はキャラクターの右手の位置や角度で移動しますが、右手はIKで銃の子要素のRightHandPositionを見ていくという
循環がおきてしまいおかしな動作になってしまいます。
その為銃は↑のようにキャラクターのEthan Spine1の子要素に移動させます。
UnityのAnimationでGunIdleアニメーションを作成する
それではUnityのAnimationで通常の銃を持っている状態GunIdleを作成していきます。
Animationに関しては
を参照してください。
Unityのメニュー→Window→Animationを選択しAnimationウインドウを開きます。
銃を選択した状態でAnimationウインドウのCreateボタンを押します。
↑のようにアニメーションを保存する画面が出るのでGunIdleという名前をつけて保存します。
アニメーションを保存するとProjectウインドウのAssetsフォルダ(デフォルトの保存先にした場合)にさきほど保存したGunIdleアニメーションと銃のアニメーターが作成されます。
また銃のアニメーターコントローラーは銃のAnimatorコンポーネントで指定されます。
銃のアニメーションはこのアニメーターコントローラーで制御する事になります。
AnimationタブでGunIdleのAdd Propertyボタンを押して銃のTransformのpositionとrotationを追加します。
Unityの実行ボタンを押します。
銃の初期位置がEthan Spine1と同じ場所にあるので移動させます。
赤丸の録画ボタンを押した状態で銃の位置や角度を変更するとタイムラインにキーフレームが打たれます。
銃の位置が決まったら銃の子要素のRightHandPositionとLeftHandPositionの位置や角度も調整しGunIdleのアニメーションにキーフレームが打たれる事を確認します。
フレーム0以外にキーフレームが打たれている場合は削除してください。
銃を選択している状態だと↑のようにTransformの背景色が通常とは変わります。
銃の位置と角度を変更し↑のように手と銃が少し見えるぐらいの位置にします。
Scene画面を見ると肘のIKを設定していない為腕が縮こまっています。
気になる方はIKHintを使い肘の角度を変更してみてください。
これでGunIdleのアニメーションが出来ました。
UnityのAnimationでWaitShotアニメーションを作成する
次は銃を構えるWaitShotを作成していきます。
↑のように新しいアニメーションクリップを作成し名前をWaitShotとします。
GunIdleのキーフレームを選択し、Ctrl+CでコピーしWaitShotのフレーム0を選択してCtrl+Vでペーストします。
さらに銃の子要素であるRightHandPositionとLeftHandPositionのpositionとrotationのプロパティを追加します。
WaitShotのフレームでUnityの実行ボタンを押し、銃を構えている状態に位置と角度を調整します。
Animationの録画ボタンを押してフレーム10の位置で銃とRightHandPosition、LeftHandPositionの位置と角度を変更します。
ここで少し難しいのはフレーム0からの角度の変更値によっては手首がグルグル回ってしまうアニメーションになる事です。
なんとか手首が回らないようにがんばってください(-.-)
360度から0、0から360度と切り替わると回転してしまうのかも?
↑のように銃を構えた後のアニメーションが出来ました。
これでGunIdleとWaitShotのアニメーションが出来上がりました。
アニメーションの遷移を作成する
最後にアニメーターコントローラーで状態の遷移を作りGunIdleからWaitShotの流れを確認してみましょう。
ProjectウインドウのAssetsフォルダにある銃のアニメーターコントローラーを選択します。
アニメーションパラメータにBool型のWaitShotを作成し、GunIdle→WaitShot、WaitShot→GunIdleへと遷移を繋げます。
遷移条件はWaitShotがtrue、falseの時に遷移させHas Exit Timeのチェックは外しておきます。
↑はGunIdleからWaitShotへの遷移条件になります。
MyCharaスクリプトにWaitShotを操作する処理を追加
次にキャラクター操作スクリプトMyChara内でアニメーションパラメータのWaitShotを操作する処理を追加します。
1 2 3 4 | [SerializeField] private Animator gunAnim; |
で銃のアニメータコントローラを設定出来るようにします。
1 2 3 4 5 6 7 | if(Input.GetButton("Fire2")) { gunAnim.SetBool("WaitShot", true); } else { gunAnim.SetBool("WaitShot", false); } |
Input.GetButton(“Fire2”)でFire2が押されていたかどうかでアニメーションパラメータのWaitShotを操作します。
デフォルトではFire2はマウスの右クリックが設定されています。
これでマウスの右クリックを押すと銃を構えるようになります。
片手IK、両手IK双方のやり方を終えて
Unityの実行ボタンを押して動作を確認してみましょう。
↑のようにGunIdleからWaitShotへの遷移が出来ました。
ただ銃がブレてしまいます(Ethan Spine1の子要素にあるので相対的に動く)
キャラクターは銃の位置と角度にIKを使い手の位置を合わせているのでこれは元のアニメーションの影響です。
キャラクターのIdleに設定しているアニメーションがHumanoidIdleで常に体が少し揺れています。
銃がブレないようにするにはIdleのアニメーションはEthan Spine1にあたるボーンの部分があまり動いていないものにするといいかもしれません。
これで両手のIKとUnityのAnimation機能で銃を構えるアニメーションが作成出来ました。
銃を撃つアニメーションも同じようにすれば作成出来ます。
さて、これで銃を持つ、銃を構える、銃を撃つアニメーションの作成が完了しました。
現状ではまだアニメーターコントローラーの設定等(片手IKの場合)を行っていないので次回やりたいと思います。
銃を持ったり、構えたり、撃ったりと言う事は移動時も出来るようにしたいので、アニメーターコントローラーのレイヤーとアバターの機能を使って部分的にアニメーションをさせ、実現したいと思います。