今回はゲーム内に操作出来るキャラクターが複数いた場合に自分で操作するキャラクターを切り替える機能を作成していきます。
ゲームに主人公の仲間がいて、その仲間だと洞窟にいる敵に対して攻撃力が高くなるといった時に、
操作するキャラクターを主人公から仲間へと変更して進めたい時があります。
そんな時に簡単に操作キャラクターを切り替えられるような機能があると便利です。
仲間のキャラクターを作成する
まずは主人公キャラクターの仲間を作成してゲーム内に配置します。
今回はサンプルなので、主人公キャラクターであるEthanをコピーして仲間キャラクターとします。
主人公キャラクターにはすでにCharacterController、Animatorが取り付けられており、キャラクターを動かすスクリプトも作成されているとします。
キャラクター操作スクリプトはControlOnOffCharaという名前にしています。
CharacterControllerは
キャラクターの移動は
アニメーターに関しては
を参照してください。
主人公キャラクターをコピーして配置したのが↑の画像です。
キャラクターはそれぞれEthan、Ethan2、Ethan3という名前にしておきます。
配置した状態で動かすと3人同時に同じ動きをしてしまいます。
まぁ・・・これは同じ機能を持ったキャラクターをコピーしたので当然ですね(-.-)
操作キャラクターを変更するスクリプトChangeCharaの作成
三人同時に動いては困るので最初はEthanだけを操作出来るようにし、Ethan2、Ethan3は操作出来ないようにしてみます。
Main Camera等に操作キャラクターを切り替えるスクリプトChangeCharaを取りつけます。
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 | using UnityEngine; using System.Collections; using System.Collections.Generic; public class ChangeChara : MonoBehaviour { // 現在どのキャラクターを操作しているか private int nowChara; // 操作可能なゲームキャラクター [SerializeField] private List<GameObject> charaList; void Start () { // 最初の操作キャラクターを0番目のキャラクターにする charaList[0].GetComponent<ControlOnOffChara>().ChangeControl(true); } void Update () { // Qキーが押されたら操作キャラクターを次のキャラクターに変更する if(Input.GetKeyDown("q")) { ChangeCharacter(nowChara); } } // 操作キャラクター変更メソッド void ChangeCharacter(int tempNowChara) { // 現在操作しているキャラクターを動かなくする charaList[tempNowChara].GetComponent<ControlOnOffChara>().ChangeControl(false); // 次のキャラクターの番号を設定 var nextChara = tempNowChara + 1; if(nextChara >= charaList.Count) { nextChara = 0; } // 次のキャラクターを動かせるようにする charaList[nextChara].GetComponent<ControlOnOffChara>().ChangeControl(true); // 現在のキャラクター番号を保持する nowChara = nextChara; } } |
現在操作しているキャラクターを把握するのがnowCharaの番号になります。
charaListには操作可能なキャラクターをインスペクタで設定出来るようにListで宣言しています。
UpdateメソッドでQキーが押されたら操作キャラクターを切り替えるChangeCharacterメソッドを呼び出します。
キャラクターの操作が可能なのはキャラクター移動スクリプトControlOnOffCharaが有効になっているからなので、キャラクターを操作したくない場合はキャラクター移動スクリプト内で自分のキャラクターがコントロール下にあるかどうかを調べて移動させるかどうかを決めます。
今回のサンプルでは複数のキャラクターの切り替えは必ず順番で行われるようにしていますが、普通のゲームであれば主人公と仲間の一人など特定の誰かと
操作を切り替えるだけなので操作キャラクターを切り替える場合にもっと単純なスクリプトで実現可能だと思います。
これでスクリプトが出来たのでChangeCharaのインスペクタでcharaListのSizeを3にしEthanをElement0、Ethan2を1、Ethan3を2にドラッグ&ドロップします。
Unityの実行ボタンを押して確認してみましょう。
↑のように一見うまく出来たあああああああ!!
と思ったら大間違い、2人目のキャラクターを操作してジャンプしている間に3人目のキャラクターに切り替えた場合、
2人目のキャラクターのCharacterControllerとキャラクター移動スクリプトControlOnOffCharaを無効化している為に重力が働かず宙に浮いたままになってしまいます。
再度2人目まで操作キャラクターを戻せば重力は働きますが、それまでは重力を無視した超人!という状態が続きます。
ゲームでキャラクターがジャンプ出来なければ問題は出ませんが、なんとなく気持ち悪いので操作キャラクターがジャンプ中に別のキャラクターに切り替えても
前のキャラクターに重力が働くようにしたいと思います。
あとは、例えば操作中でないキャラクターも敵の攻撃を受けるようにしたい場合CharacterControllerのコライダやキャラクター操作スクリプトが必要になります。
キャラクター操作スクリプト内でこのキャラクターが操作中であるかどうかのデータcontrolフラグを作成し、操作中だけ移動の処理が出来るようにします。
ControlOnOffCharaスクリプトに処理を記述していきます。
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 | using UnityEngine; using System.Collections; public class ControlOnOffChara : MonoBehaviour { private CharacterController characterController; private Animator animator; private Vector3 velocity = Vector3.zero; [SerializeField] private float walkSpeed = 1.5f; // 現在キャラクターを操作出来るかどうか private bool control; // Use this for initialization void Awake () { characterController = GetComponent <CharacterController> (); animator = GetComponent <Animator> (); } // Update is called once per frame void Update () { if (characterController.isGrounded) { velocity = Vector3.zero; if (control) { var input = new Vector3 (Input.GetAxis ("Horizontal"), 0f, Input.GetAxis ("Vertical")); if (input.magnitude > 0f) { animator.SetFloat ("Speed", input.magnitude); transform.LookAt (transform.position + input); velocity = transform.forward * walkSpeed; } else { animator.SetFloat ("Speed", 0f); } if (Input.GetButtonDown ("Jump")) { velocity.y += 5f; } } } velocity.y += Physics.gravity.y * Time.deltaTime; characterController.Move (velocity * Time.deltaTime); } public void ChangeControl(bool controlFlag) { control = controlFlag; animator.SetFloat("Speed", 0f); } } |
AwakeメソッドでCharacterControllerとAnimatorを取得しています。
これはChangeControlメソッドでアニメーションパラメータを変更していますが、このChangeControlメソッドはChangeCharaスクリプトのStartメソッドから呼ばれるので、Startメソッドより早いタイミングのAwakeでAnimatorを取得しておく必要があるからです。
controlフラグを用意し、今このキャラクターを操作出来る状態かどうかを判定出来るようにします。
移動の操作が行われるのはcontrolがtrueの時だけになるよう移動処理の部分を条件付きにしています。
ジャンプや攻撃といった処理も操作中のみ出来るようにします。
こうすることでコントロール下にないキャラクターの場合は操作が出来なくなりますが、重力は働いており操作中に別キャラクターに切り替えても地面まで落下します。
移動スクリプトControlOnOffCharaの無効化はしていないので敵から攻撃を受けた時の処理も追加出来ます。
それではUnityの実行ボタンを押して確認してみましょう。
↑のようにジャンプ中に操作キャラクターを切り替えてもちゃんと落下するようになりました。
これでUnityのゲームで操作キャラクターを切り替える機能が完成しました。
操作キャラクター自体が操作中かどうかという情報を持っているので処理が楽ですね。
キャラクターのモデルを変更し、キャラクターそれぞれは同じ操作スクリプトで制御しつつ、Animatorでアニメーションを変更したりするだけでそれぞれの動きをしてくれますから。
こういったところはオブジェクト指向言語のいい所ですね(^^)v