今回までで銃を撃つ、持っている弾の数を減らすという事は出来ていました。
銃を撃つ機能は

を参照してください。
弾を減らしてUIで表示する機能は

を参照してください。
しかし銃に弾を装填する機能までは作成していなかったので、今回作成していきます。
銃に弾を装填する時に使うアニメーションの用意
弾の装填は銃のマガジン(弾が入っている所)を取り出し、新しいマガジンをはめこむというアニメーションを用意し、アニメーションが終わったら銃に装填出来る弾の数だけ装填します。
マガジンごと変更しているので残っている弾もなくなるはずという突っ込みはなしでお願いします・・・・(^_^;)
銃はマガジンを変更出来る物に限定しております。
マガジンを変更するアニメーションを用意してください。
マグナムとかマシンガンとかはまた別のアニメーションが必要になると思います。
ご自分でアニメーションを作成する方は

を参考にしてください。
弾を装填するアニメーションは上のような感じになります。
遷移のアニメーションを切り取ったので本来のアニメーションとは違いますが、
本来は銃を構えた状態からマガジンをはめこむまでのアニメーションです。
主人公キャラのアニメーターコントローラーの作成
それでは主人公キャラクターのアニメーターコントローラーに状態と遷移を作成していきましょう。
アニメーションパラメータにChargeBulletをTriggerで作成します。
このChargeBulletがTriggerされた時に弾を装填するアニメーションへと遷移させます。
上のようにChargeBullet状態を作り、弾を装填するアニメーションクリップを設定します(アニメーションクリップは後で作成し設定します)。
WaitShotからChargeBulletに右クリック→Make Transitionし遷移を繋げます。
Has Exit Timeのチェックを外し、ChargeBulletがトリガーされたらすぐに遷移するようにします。
ChargeBullet→WaitShotへと遷移を繋げ、Has Exit Timeのチェックを入れ、条件には何も入れません。
Has Exit Timeにチェックが入っているのでアニメーションが終了したら自動で遷移します。
ChageBullet→WaitShotのアニメーションブレンドではWaitShotの銃を構えるアニメーションの銃を構え終わった時の状態に遷移させたいので、WaitShotアニメーションの最後の方だけブレンドしすぐに銃を構え終わった時にしています。
これでキャラクターのアニメーターコントローラの設定が終わりました。
キャラクターの動きに合わせて銃のマガジンを動かすアニメーションの作成
次はキャラクターのアニメーションに合わせて銃のマガジンを取り出し、はめ込むアニメーションを作成していきます。
では弾の装填をするアニメーションに合わせて銃のマガジンの移動を合わせていきます。
キャラクターのマガジンをはめ込むアニメーションを調べる
まずは弾の装填を開始する位置を調べる為にキャラクターを選択しAnimationタブを表示します。
上のようにAnimationタブを表示したら、画像のrig | Bullet (Read – Only)となっている個所をクリックし弾を装填するアニメーションを選択します。
rig | Bullet(Read – Only)の部分はわたくしの場合そういう名前になっているだけで、他の表示がされているはずです。
ここで、Animationの再生位置(時間が表示されている部分)をマウスドラッグして移動するとSceneタブのキャラクターがそのアニメーションを再生するので、手がマガジンをはめこみ始める場所を見つけます。
(一旦手が下がり、銃に向かって上がっていく所を探します)
Sceneタブだと上のような位置が0:10当たりになる事がわかりました。
またはめ込みが終わる時間(キャラクターの弾の装填アニメーションの再生終わり時間)が1:06秒です。
銃のマガジンのアニメーションの作成
マガジンをはめこみ始める時間がわかったので、銃のマガジンのアニメーションを作成します。
銃のアニメーションに関しては

を参考にしてください。
銃のプレハブをヒエラルキー上にドラッグ&ドロップ(キャラクターの子要素)し、手に持たせた時の位置と同じ位置に移動します。
その後、銃をドラッグ&ドロップでキャラクターの子要素から外します(自身が一番上の親となる)。
これで銃の位置はキャラクターの手の位置にありますが、銃は他のゲームオブジェクトの子要素にはない状態になります。
銃をキャラクターの子要素のまま銃のアニメーションを作成すると、変な不具合(キャラクターのコライダが別の部分に移動して元に戻らなくなる)が発生した為です。
銃のアニメーターコントローラーを選択し、Trigger型のChargeというアニメーションパラメータを作成します。
銃のマガジンの移動状態ChargeBulletを作成します。
GunIdle→ChargeBulletは上のように設定します。
ChargeBullet→GunIdleは上のようにします。
ではChargeBulletに設定する銃のアニメーションを作成していきます。
キャラクターが装備している銃を選択し、Animationタブを表示します。
上のCreate New Clipを選択しChargeBulletという名前を付けます(画像ではすでに作られていますが)。
Add PropertyをクリックしMagazineのPositionを追加します。
MagazineのPositionをシーン上で確認しながら位置を記憶させます。
上の画像のように0:00、0:10、1:06の位置にキーフレームを作成します(フレーム上で右クリックからAdd Key)。
0:10はキャラクターのアニメーションでマガジンをはめこみ始める時間で、1:06がはめ込み終わる時間です。
Unityを実行して主人公キャラクターを選択しAnimationウインドウでマガジンを銃にはめるアニメーションを選択し0:10の位置に移動させます。
Unityを一時停止して銃のインスタンスを選択しAnimationウインドウでアニメーションを作成していきます。
上が0:00秒の時のマガジンの位置です。
マガジンを取り外して移動させる為に遠い場所に設定します。
特別遠くに作らなくても0:10の辺りにあれば大丈夫です(0:10と同じ位置で構いません)。
GunIdle→ChargeBulletへと遷移するので、銃にはめ込まれているマガジンからここで設定した位置に遷移していきます。
0:10はマガジンをはめこみ始める位置なのでマガジンの位置を手の当たりに持っていきます。
Unityの実行ボタンを押してすぐに一時停止しコマ送りで位置を調整するといいかもしれません。
(他にもっといい方法があるかも?)
1:06の時はマガジンをはめこみ終わった時なので、本来の位置に合わせます。
次に0:00から0:10の間はマガジンを表示しないようにします。
まずはMagazineのIsActiveプロパティを追加します。
次に0:00のMagazineのIs Activeのチェックを外し、0:10でチェックを入れます。
こうすることで、マガジンをはめようとし始める時からマガジンが表示されるようになります。
銃のアニメーションの作成が終わったらヒエラルキー上の武器はApplyをして削除します。
武器のステータスを保持しているスクリプトWeaponStatusの修正
とりあえずこれでアニメーション関連は完成したので、次はスクリプトに処理を追加していきます。
弾を装填するには銃を構えている状態で左シフトキーまたはPS3コントローラーの×ボタンを押した時にする事にします。
PS3コントローラー等のゲームパッドを使いたい場合は

を参考にしてください。
弾の全体の数はキャラクターのステータススクリプトMyStatusに保持し、銃に装填している弾の数は武器のステータスWeaponStatusに保持するように変更します。
今回はWeaponStatusに銃に装填している弾の数を保持していますが、武器の切り替え時に毎回武器のプレハブをインスタンス化している場合に弾の装填数が毎回リセットされてしまいます。
武器を毎回インスタンス化しない場合は問題ないですが、毎回インスタンス化する場合は銃毎の弾の装填数を別途キャラクターステータスで保持しておいた方がいいかもしれません。
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | using UnityEngine; using System.Collections; public class WeaponStatus : MonoBehaviour { [SerializeField] private int attackPower; [SerializeField] private int shotPower; [SerializeField] private ItemDataBase.Item itemType; [SerializeField] private float weaponRange; // 銃に装填出来る弾の数 [SerializeField] private int limitChargeBullet; // 現在装填している弾の数 [SerializeField] private int chargeBullet; // インスタンス化した時の武器の位置、角度、サイズデータ [SerializeField] private Vector3 pos; [SerializeField] private Vector3 rot; [SerializeField] private Vector3 scale; // 打撃系攻撃力を返す public int GetAttackPower(){ return attackPower; } // 銃で撃った時の攻撃力を返す public int GetShotPower(){ return shotPower; } // アイテムタイプを返す public ItemDataBase.Item GetWeaponType() { return itemType; } // 銃の射程距離を返す public float GetWeaponRange() { return weaponRange; } // 手に持たせる時のローカル位置を返す public Vector3 GetPos() { return pos; } // 手に持たせる時のローカル角度を返す public Vector3 GetRot() { return rot; } // 手に持たせる時のスケールを返す public Vector3 GetScale() { return scale; } // 銃に装填出来る弾の最大数を返す public int GetLimitChargeBullet() { return limitChargeBullet; } // 銃に弾を装填する数を設定 public int SetChargeBullet(int bulletNum) { this.chargeBullet = bulletNum; return this.chargeBullet; } // 銃に装填している弾の数を返す public int GetChargeBullet() { return chargeBullet; } } |
上がWeaponStatusスクリプトです。
limitChargeBulletは銃に装填出来る最大数で、chargeBulletが現在の装填数です。
銃のWeaponStatusのインスペクタでlimitChangeBulletとchargeBulletの値を設定してください。
銃に弾を装填させる為の処理を主人公操作スクリプトに追加
キャラクター操作スクリプトに弾を装填する処理を追加していきます。
弾を装填出来るのはダメージを受けていない時にします。
以前の記事から機能を作成している方はキャラクター操作スクリプトのUpdateメソッド内でキャラクターの状態に応じて処理を分けている部分に追記します。
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 35 36 37 38 39 40 41 42 | } else if (state == MyState.WaitShot) { // マウスの右ボタンを離したらノーマル状態へ遷移 if (!Input.GetButton("Fire2")) { //spineXAxis = 0; //spineZAxis = 0; isHoldGun = false; animator.SetBool("WaitShot", false); shot.DisableLight(); shot.DisableRaserPointer(); SetState(MyState.Normal); autoRotateCamera.SetIsWaitShot(false); // ハンドガンを装備している時だけ弾を装填出来るようにする } else if (Input.GetButtonDown("Fire3")) { SetState(MyState.ChargeBullet); // 構えた状態 } else { shot.AbleRaserPointer(); // 銃を撃つ if (Input.GetButtonDown("Fire1")) { shot.JudgeShot(); } autoRotateCamera.SetIsWaitShot(true); } // 弾を装填している状態 } else if (state == MyState.ChargeBullet) { if (!animator.GetCurrentAnimatorStateInfo(0).IsName("ChargeBullet") && !animator.IsInTransition(0) ) { // 銃の最大数まで装填するか、持ち弾がなくなったら終了 for (var i = 0; myStatus.GetWeaponStatus().GetChargeBullet() < myStatus.GetWeaponStatus().GetLimitChargeBullet() && myStatus.GetNumberOfBullet() > 0; i++ ) { myStatus.GetWeaponStatus().SetChargeBullet(myStatus.GetWeaponStatus().GetChargeBullet() + 1); myStatus.SetNumberOfBullet(myStatus.GetNumberOfBullet() - 1); bulletNumText.text = myStatus.GetWeaponStatus().GetChargeBullet().ToString(); } // チャージが終了したらノーマル状態へ SetState(MyState.WaitShot); } } |
銃を構えている状態でFire3に対応するボタンが押されたら状態を弾を装填する状態に変更します。
弾を装填する状態の時はChargeBullet状態にいない時で遷移途中でない時に、弾の装填が終わったとして銃の弾の数を変更します。
これは弾を装填中にダメージを受けた時は弾を装填出来なかったとする為で、弾の装填アニメーションが終わるまで弾の数を変更しないようにします。
弾の数は銃に装填出来る弾の最大数を超えていない時で、キャラクターが弾を1つでも持っている時はループで処理を繰り返し弾の装填数を増やします。
キャラクターの状態変更メソッドSetStateの修正
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 | public void SetState(MyState tempState) { state = tempState; velocity = Vector3.zero; animator.SetFloat("Speed", 0f); animator.SetFloat("Rotate", 0f); if (state == MyState.Normal) { } else if (state == MyState.Attack) { animator.SetTrigger("Attack"); } else if (state == MyState.Damage) { animator.SetBool("WaitShot", false); animator.SetTrigger("Damage"); } else if (state == MyState.WaitShot) { } else if (state == MyState.ChargeBullet) { //shot.DisableLight(); autoRotateCamera.SetIsWaitShot(false); spineXAxis = 0f; spineZAxis = 0f; isHoldGun = false; animator.SetTrigger("ChargeBullet"); myStatus.GetEquip().GetComponent<Animator>().SetTrigger("Charge"); } } |
キャラクターを弾を装填状態へと変更する時にいくつかのリセットをする必要があります。
これは銃を構えた状態でキャラクターの上半身を動かしていた時に弾を装填するようにすると、上半身の変更値等をリセットせず状態が変更してしまう為です。
なので、銃を構えた時に変更していた値等をリセットしています。
リセット処理が終わったら、キャラクターのアニメーションパラメータのChargeBulletをトリガーし銃の装填アニメーションにし、装備している武器のアニメーションパラメータChargeのトリガーをし、銃のマガジンをはめ込むアニメーションを再生します。
銃を撃った時に弾の数を銃に入っているものから減らす
銃を撃った時にキャラクターが持っている弾の総数から1つ減らしていましたが、銃の装填数を決めた事で銃自体に装填されている弾の数を減らすようにしなければいけません。
以前から機能を作成している方はShotスクリプトのJudgeShotメソッド内で弾を減らしている箇所を修正します。
1 2 3 | bulletText.text = myStatus.GetWeaponStatus().SetChargeBullet (myStatus.GetWeaponStatus ().GetChargeBullet () - 1).ToString (); |
キャラクターが装備している武器に装填されている弾の数を減らすようにします。
弾の装填がうまくいくか確認してみましょう
それではUnityの実行ボタンを押して確認してみましょう。
上が実行結果です。
注意するべき点として、アニメーターコントローラーの状態を選択して、キャラクターの弾の装填アニメーションクリップのSpeedを変更する時は銃のマガジンの移動のアニメーションスピードも同じ値にする必要があります。
キャラクターの動作を秒数で調べ、それに合わせて銃のマガジンの移動をさせた為です。
今回の内容は他の色々な要素が合わさって出来ているので、非常に解りづらいです。
以前の記事の機能が出来ていないと今回の記事だけでは弾の装填の機能が完成出来ないので、
フラストレーションの溜まる方もいるかもしれませんが、ご了承くださいm(__)m
元々装備出来る武器はキャラクターの子要素に見えないように配置し、装備している武器だけを見える仕様にしていた為、弾の装填数を武器のステータススクリプトに保持しても問題はなかったんですが、
武器の切り替えを毎回インスタンス化するように変更してしまった為、武器を切り替える度に弾の装填数が0になってしまいます。
銃に装填した弾の数をキャラクターステータススクリプト等で保持するようにし、銃に切り替えたらその数を設定するようにするしかないかもしれません。