今回は主人公キャラが持っている武器を特定のキーを押したら切り替えられるようにしてみます。
前回までで、敵キャラ、主人公の双方の攻撃とダメージの機能が出来ました。
初期設定として懐中電灯を持つようにし、キーの1を押すと次の武器の剣に切り替えます。
さらにキーを押すと次の武器または持ち物に変更します。
今回はキーの1を押すごとに順番に武器を切り替える仕様にしています。
今回の機能を作成すると、
↑のように装備している武器を切り替える事が出来るようになります。
今回はとりあえず武器の切り替えが出来るという最低限の機能を追加します。
あらかじめ装備品をヒエラルキー上に置いておくパターンと装備品をプレハブ化し、その都度インスタンス化するパターンを作っていきます。
今回の機能は以前の記事で作成した主人公操作スクリプトであるCharacterScriptスクリプト等が使われています。
なので既に作成済みの機能は
の記事で機能作成の流れが確認出来ますので、この機能は何?と思ったら確認してみてください。
武器をキャラクターに持たせる
今まで懐中電灯や剣を右手の子要素として設置していましたが、右手の子要素にEquipという空のゲームオブジェクトを作り、そこに合うように懐中電灯と剣の位置、角度を合わせて配置します。
武器の合わせ方は
を参考にしてください。
Equipは上のような感じで配置します(Equipに一時的にCapsule Collider等を取り付けて位置と角度を調整するとわかりやすいです)。
Scaleの値は必ず1にしておいてください。
子のTransform(位置情報)は親の位置やScaleの相対値になっていく為、Equipの子要素にも影響が出てしまう為です。
キャラクターは物を持っているようにアニメーションさせていないので合わせづらいですが、Equipに取り付けた一時的なコライダが手の位置になんとなくくるように合わせます。
手の部分だけに別のアニメーションを適用させると合わせるのが簡単になります。
手等の一部を部分的にアニメーションさせたい場合は
の記事を参考にしてください。
Equipには新しいスクリプトChangeEquipを追加します。インスペクタの値は後で設定します。
Equipは装備を配置する目印なのでMeshとコライダは無効にしておきます。
(間違って3DオブジェクトのCubeでやってしまったのでこうなっています)
武器を切り替えるスクリプトChageEquip
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 | using UnityEngine; using System.Collections; public class ChangeEquip : MonoBehaviour { [SerializeField] private GameObject[] weapons; private int equipment; private ProcessCharaAnimEvent processCharaAnimEvent; private CharacterScript characterScript; // Use this for initialization void Start() { characterScript = GetComponentInParent<CharacterScript>(); processCharaAnimEvent = transform.root.GetComponent<ProcessCharaAnimEvent>(); // 初期装備設定 equipment = 0; weapons[equipment].SetActive(true); } // Update is called once per frame void Update() { if (Input.GetKeyDown("1") && characterScript.GetState() == CharacterScript.MyState.Normal) { ChangeWeapon(); } } void ChangeWeapon() { equipment++; if (equipment >= weapons.Length) { equipment = 0; } // 武器を切り替え for (var i = 0; i < weapons.Length; i++) { if (i == equipment) { weapons[i].SetActive(true); processCharaAnimEvent.SetCollider(weapons[i].GetComponent<Collider>()); } else { weapons[i].SetActive(false); } } } } |
装備する武器はEquipの子要素に並べておき、インスペクタでweaponsに設定するようにします。
現在装備している武器はweapons配列の何番目かをequipmentで持つようにします。
Startメソッドでは主人公操作スクリプトのCharacterScriptと主人公のアニメーションイベント受け取りスクリプトのProcessCharaAnimEventを取得します。
最初の武器のゲームオブジェクトをアクティブにします。
Updateメソッドでは1キーを押した時に主人公がノーマル状態の時だけ武器を変更出来るようにします。
ChangeWeaponメソッドが実際に武器を切り替えている処理で、まずは配列要素番号を+1した後に、その武器のゲームオブジェクトをアクティブにし、他のゲームオブジェクトを非アクティブにしています。
装備を変えたらProcessCharaAnimEventのSetColliderメソッドで武器のコライダも変更します。
ProcessCharaAnimEventにSetColliderの追加と他のフィールド宣言等を変更します。
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 System.Collections; using System.Collections.Generic; using UnityEngine; public class ProcessCharaAnimEvent : MonoBehaviour { private CharacterScript characterScript; [SerializeField] private Collider weaponCollider; private void Start() { characterScript = GetComponent<CharacterScript>(); } void AttackStart() { weaponCollider.enabled = true; } void AttackEnd() { weaponCollider.enabled = false; } void StateEnd() { characterScript.SetState(CharacterScript.MyState.Normal); } public void EndDamage() { characterScript.SetState(CharacterScript.MyState.Normal); } public void SetCollider(Collider col) { weaponCollider = col; } } |
capColは元々CapsuleColliderで宣言していましたが、宣言部分でColliderに変更しておきます。
武器によってはCapsuleColliderではなくBoxCollider等を使う場合を考えてこうしておきます。
いわゆる多態性というやつでコライダは色々あるけどみんなコライダだという扱いをします。
太郎や花子など色々な人はいるけれどみんな人間という種族として取り扱うという事になります。
これで二つの武器(というかひとつは懐中電灯ですが・・・)の切り替えが出来るようになりました。
ProcessCharaAnimEventのweaponColliderにはあらかじめFlashLightゲームオブジェクトをドラッグ&ドロップし懐中電灯のコライダを設定しておきます。
スクリプトで武器をインスタンス化し装備させる方法もある
最初から武器を設定し非アクティブにしておくのではなく、プレハブのインスタンス化をしてEquipの場所に表示するという方法もあります。
これならばヒエラルキー上に武器が何十個も表示される事がなく、スクリプト上でインスタンス化し配置する事が出来ます。
Equipの子要素に配置した懐中電灯や剣をAssetsフォルダにドラッグ&ドロップしプレハブにします。
その後、剣等をキャラクターに正しく持たせたTransformのPosition、Rotation、Scaleの値をメモ帳等に書いておきます。
これは剣等のプレハブをインスタンス化した時に正確な位置や回転、サイズに合わせる為です。
これが終わったらヒエラルキー上のEquipの子要素の装備品は削除します。
ChangeEquipスクリプトを修正します。
まずはStartメソッドでequipmentに-1を入れます。
1 2 3 4 5 6 7 8 9 | void Start () { move = GetComponentInParent<Move>(); processMyAttack = transform.root.GetComponent<ProcessMyAttack>(); // 初期装備設定 equipment = -1; } |
weapons[equipment].SetActive(true);
は削除します。
次にUpdateメソッドでChangeメソッドではなくInstantiateWeaponメソッドを呼び出すようにします。
1 2 3 4 5 6 7 8 | void Update() { if (Input.GetKeyDown("1") && characterScript.GetState() == CharacterScript.MyState.Normal) { InstantiateWeapon(); } } |
最後に装備品をインスタンス化するInstantiateWeaponメソッドを追記します。
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 | void InstantiateWeapon() { equipment++; if (equipment >= weapons.Length) { equipment = -1; } // 今装備している武器を削除 if (transform.childCount != 0) { Destroy(transform.GetChild(0).gameObject); } // 素手ではない時だけ武器をインスタンス化 if (equipment != -1) { // 新しく装備する武器をインスタンス化 var weapon = Instantiate<GameObject>(weapons[equipment]); processCharaAnimEvent.SetCollider(weapon.GetComponent<Collider>()); // サンプルの為、直接武器の位置や角度を設定 if (equipment == 0) { weapon.transform.SetParent(transform); weapon.transform.localPosition = new Vector3(0.002f, 0.035f, 0.065f); weapon.transform.localEulerAngles = new Vector3(315f, 99f, 264f); weapon.transform.localScale = new Vector3(0.03f, 0.1f, 0.03f); } else { weapon.transform.SetParent(transform); weapon.transform.localPosition = new Vector3(0.004f, 0.029f, 0.065f); weapon.transform.localEulerAngles = new Vector3(345f, 275f, 84f); weapon.transform.localScale = new Vector3(1f, 1f, 1f); } } } |
今装備している武器があればその武器を削除し、インスペクタでweapons配列に先ほどプレハブ化した装備品をドラッグ&ドロップしておきます。
先ほどはヒエラルキーの装備品をインスペクタで設定しましたが、今回はプレハブ化した装備品を設定する必要があります。
武器をインスタンス化したらその武器のColliderコンポーネント(CapsuleColliderやBoxCollider等)をProcessCharaAnimEventのSetColliderメソッドで設定します。
インスタンス化した武器の親要素はTransformのSetParentメソッドで自身(このスクリプトが設定されているゲームオブジェクト)であるEquipにします。
今回は懐中電灯と剣の2つの武器だけを設定したと想定していて、手動でそれぞれの位置や角度、サイズをインスタンス化した装備品に割り当てます。
ここで設定する数値は先ほどメモ帳に残したデータを記述します。
本来であれば武器のパラメータ等を保持するスクリプトを武器自体に設定しておき、そこからインスタンス化した時の位置や角度、サイズを設定するようにすればいいと思います。
今回は2つだけなので手動で設定しました。
ここら辺は
↑の服の着せ替えの記事でやっているのでそちらも参考にしてください。
装備を切り替える時に何も装備していない時はコライダの切り替えが出来ないので、ProcessCharaAnimEventスクリプトを修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 | void AttackStart() { if (weaponCollider != null) { weaponCollider.enabled = true; } } void AttackEnd() { if (weaponCollider != null) { weaponCollider.enabled = false; } } |
1キーを押すとEquipの子要素の装備品が削除されたり、インスタンス化され表示されるようになりました。
これで武器の切り替えが終了しました。
次回は敵に当たったエフェクトを設定してみます。