Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9547

[Unity]2D牧場ゲームを作ってみる その4[キャラクターの移動・会話処理を切り分け]

$
0
0
前置き 前回の記事で、他のキャラクターに話しかけたときにメッセージを表示をするように実装しました。 [Unity]2D牧場ゲームを作ってみる その3[メッセージ表示] 今回作成するものは大きく分けて以下の2つになります。 主人公のキャラクターが会話している時は移動処理をしない。 会話が終了したら移動処理に切り替えるようにする。 前回までの実装した動きは以下になります。 会話中に→キーを押しているため、ずっと右に進んでいますね…。 会話中は移動しないように修正していきます。 今回作成するもの 1.キャラクターの移動・会話処理の切り分けスクリプトMoveAndTalkCharaの追加 2.メッセージ表示のスクリプトMessageCharactorの変更 3.フィールドオブジェクトの基本処理のスクリプトFieldObjectBase.csの変更 4.キー操作にあわせアニメーションに状態をわたすスクリプトAnimationStateController.csの変更 1.キャラクターの移動・会話処理の切り分けスクリプトMoveAndTalkChara.csの追加 新規にMoveAndTalkChara.csを作成しました。このスクリプトは主人公のキャラクターの移動と会話処理を切り分けるものとなります。 参考にしたサイト:Unityでキャラクターの移動と会話処理を切り分ける 1-1~1-4で説明をした後、1-5でMoveAndTalkChara.csの全体を載せます。 1-1.キャラクターの状態を列挙型で作成 キャラクターが移動している状態、会話している状態を列挙型で作成し、キャラクターがその状態を保持できるようにします。 移動している状態はnormal、会話している状態はtalkと設定します。他の状態を作成する時は、CharacterStateに追加していきましょう。 キャラクターの状態をcharacterStateに保持するようにします。 public enum CharacterState{ normal, talk } private CharacterState characterState; 1-2.Updateメソッドで行動処理を分ける Updateメソッドで、行動処理をわけます。 キャラクターが移動している状態ではMove()、会話している状態ではTalk()と呼び出すようにします。 animationStateController.~は4のAnimationStateController.csで説明します。 void Update(){ if(characterState == CharacterState.normal){ animationStateController.MoveAnimation(); Move(); }else if(characterState == CharacterState.talk){ animationStateController.NoMoveAnimation(); Talk(); } } 1-3.MoveとTalkメソッド UpdateメソッドでMoveとTalkメソッドを呼び出しているのでその中身を記述します。 MoveではMoveController.csのコードを設定します。そのためMoveController.csは不要になるため、主人公のキャラクターのInspectorからチェックを外しましょう。 Talkは会話中に何かしら処理を入れたい時に入れましょう。 void Move(){ // 入力を取得 input = new Vector2( Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")); if (input == Vector2.zero) { return; } rigidBody.position += input * SPEED * Time.deltaTime; } void Talk(){ } 1-4.主人公の状態の取得と設定の処理 主人公の状態を取得したり、状況を切り替える必要があるので、そのための処理を記述します。 // 状態確認メソッド public CharacterState GetState(){ return characterState; } // 状態変更メソッド public void SetState(CharacterState setState){ characterState = setState; } 1-5.MoveAndTalkChara.csの全体 1~1から1~4で説明したコードをまとめたいと思います。 using System.Collections; using System.Collections.Generic; using UnityEngine; public class MoveAndTalkChara:MonoBehaviour{ public float SPEED = 0.5f; private Rigidbody2D rigidBody; private Vector2 input; public enum CharacterState{ normal, talk } private CharacterState characterState; AnimationStateController animationStateController; Animator animator; void Start(){ this.rigidBody = GetComponent<Rigidbody2D>(); characterState = CharacterState.normal; this.animator = GetComponent<Animator>(); animationStateController = GameObject.Find("char_crol_0").GetComponent<AnimationStateController>(); } void Update(){ if(characterState == CharacterState.normal){ animationStateController.MoveAnimation(); Move(); }else if(characterState == CharacterState.talk){ animationStateController.NoMoveAnimation(); Talk(); } } void Move(){ // 入力を取得 input = new Vector2( Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")); if (input == Vector2.zero) { return; } rigidBody.position += input * SPEED * Time.deltaTime; } void Talk(){ } // 状態確認メソッド public CharacterState GetState(){ return characterState; } // 状態変更メソッド public void SetState(CharacterState setState){ characterState = setState; } } 2.メッセージ表示のスクリプトMessageCharactor.csの変更 MessageCharactor.csに3つのコードを追加しました。 moveAndTalkChara.SetState(MoveAndTalkChara.CharacterState.talk); 会話をする時に、talkに設定 moveAndTalkChara.SetState(MoveAndTalkChara.CharacterState.normal); 移動する時に、normalに設定 using System.Collections; using UnityEngine; using UnityEngine.UI; using System.Collections.Generic; public class MessageCharactor : FieldObjectBase { // セリフ : Unityのインスペクタ(UI上)で会話文を定義する   // (次項 : インスペクタでscriptを追加して、設定をする で説明) [SerializeField] private List<string> messages; MoveAndTalkChara moveAndTalkChara; void Start(){ moveAndTalkChara = GameObject.Find("char_crol_0").GetComponent<MoveAndTalkChara>(); } // 親クラスから呼ばれるコールバックメソッド (接触 & ボタン押したときに実行) protected override IEnumerator OnAction() { for (int i = 0; i < messages.Count; ++i) { moveAndTalkChara.SetState(MoveAndTalkChara.CharacterState.talk); // 1フレーム分 処理を待機(下記説明1) yield return null; // 会話をwindowのtextフィールドに表示 showMessage(messages[i]); // キー入力を待機 (下記説明1) // yield return new WaitUntil(() => Input.anyKeyDown); yield return new WaitUntil(() => Input.GetKeyDown(KeyCode.Space)); } moveAndTalkChara.SetState(MoveAndTalkChara.CharacterState.normal); yield break; } } 3.フィールドオブジェクトの基本処理のスクリプトFieldObjectBase.csの変更 Fixedupdate()をUpdate()に変更しただけになります。 変更理由は、Fixedupdate()だとキーを押しているのに入力されない、反応しない、反応する時としない時があるためです。 【Unity】 FixedUpdate と Input.GetKeyDown 変更点は少ないですが、全体のコードは以下になります。 using System.Collections; using UnityEngine; using UnityEngine.UI; /** * フィールドオブジェクトの基本処理 */ public abstract class FieldObjectBase : MonoBehaviour { // Unityのインスペクタ(UI上)で、前項でつくったオブジェクトをバインドする。   // (次項 : インスペクタでscriptを追加して、設定をする で説明) public Canvas window; public Text target; // 接触判定 private bool isContacted = false; private IEnumerator coroutine; // colliderをもつオブジェクトの領域に入ったとき(下記で説明1) private void OnTriggerEnter2D(Collider2D collider) { isContacted = collider.gameObject.tag.Equals("Player"); } // colliderをもつオブジェクトの領域外にでたとき(下記で説明1) private void OnTriggerExit2D(Collider2D collider) { isContacted = !collider.gameObject.tag.Equals("Player"); } private void Update() { if (isContacted && coroutine == null && Input.GetButton("Submit") && Input.anyKeyDown) { coroutine = CreateCoroutine(); // コルーチンの起動(下記説明2) StartCoroutine(coroutine); } } /** * リアクション用コルーチン(下記で説明2) */ private IEnumerator CreateCoroutine() { // window起動 window.gameObject.SetActive(true); // 抽象メソッド呼び出し 詳細は子クラスで実装 yield return OnAction(); // window終了 this.target.text = ""; this.window.gameObject.SetActive(false); StopCoroutine(coroutine); coroutine = null; } protected abstract IEnumerator OnAction(); /** * メッセージを表示する */ protected void showMessage(string message) { this.target.text = message; } } 4.キー操作にあわせアニメーションに状態をわたすスクリプトAnimationStateController.csの変更 UpdateメソッドをMoveAnimationに変更しましょう。 移動しない、会話の時はNoMoveAnimationを呼び出します。 public void MoveAnimation() { if (Input.anyKeyDown) { Vector2? action = this.actionKeyDown(); if (action.HasValue) { // キー入力があればAnimatorにstateをセットする setStateToAnimator(vector: action.Value); return; } } // 入力からVector2インスタンスを作成 Vector2 vector = new Vector2( (int)Input.GetAxis("Horizontal"), (int)Input.GetAxis("Vertical")); // キー入力が続いている場合は、入力から作成したVector2を渡す // キー入力がなければ null setStateToAnimator(vector: vector != Vector2.zero? vector : (Vector2?)null); } public void NoMoveAnimation(){ this.animator.speed = 0.0f; } 2つのメソッドを追加しました。あまり変更点はないです。 全体のコードは以下になります。 using System.Collections; using System.Collections.Generic; using UnityEngine; /** * キャラの向き状態を変更するController */ public class AnimationStateController : MonoBehaviour { Animator animator; void Start() { // Animatorを取得する this.animator = GetComponent<Animator>(); } /** * Update は MonoBehaviour が有効の場合に、毎フレーム呼び出されます * https://docs.unity3d.com/ja/current/ScriptReference/MonoBehaviour.Update.html */ // void Update() { public void MoveAnimation() { if (Input.anyKeyDown) { Vector2? action = this.actionKeyDown(); if (action.HasValue) { // キー入力があればAnimatorにstateをセットする setStateToAnimator(vector: action.Value); return; } } // 入力からVector2インスタンスを作成 Vector2 vector = new Vector2( (int)Input.GetAxis("Horizontal"), (int)Input.GetAxis("Vertical")); // キー入力が続いている場合は、入力から作成したVector2を渡す // キー入力がなければ null setStateToAnimator(vector: vector != Vector2.zero? vector : (Vector2?)null); } public void NoMoveAnimation(){ this.animator.speed = 0.0f; } /** * Animatorに状態をセットする * */ private void setStateToAnimator(Vector2? vector) { if (!vector.HasValue) { this.animator.speed = 0.0f; return; } Debug.Log(vector.Value); this.animator.speed = 1.0f; this.animator.SetFloat("x", vector.Value.x); this.animator.SetFloat("y", vector.Value.y); } /** * 特定のキーの入力があればキーにあわせたVector2インスタンスを返す * なければnullを返す */ private Vector2? actionKeyDown() { if (Input.GetKeyDown(KeyCode.UpArrow)) return Vector2.up; if (Input.GetKeyDown(KeyCode.LeftArrow)) return Vector2.left; if (Input.GetKeyDown(KeyCode.DownArrow)) return Vector2.down; if (Input.GetKeyDown(KeyCode.RightArrow)) return Vector2.right; return null; } } 完成 次に作成するもの(仮) アイテムの持ち上げ関係 参考にしたサイト Unityでキャラクターの移動と会話処理を切り分ける 【Unity】 FixedUpdate と Input.GetKeyDown

Viewing all articles
Browse latest Browse all 9547

Trending Articles