列挙型enum
を用いて分岐をする際に,同じ命令で2つの列挙子を切り替える方法です。
(Unity 2018.3.0f2)
続編記事にて,拡張メソッドとして改良した物を御紹介しております。
列挙型enum
の使いかたについては,以下の記事を御覧ください。
「画面をクリック(タップ)するたびに,数字のカウントアップと回転を切り替える」というプログラムを作ります。
元のコード
using UnityEngine; public class NewBehaviourScript : MonoBehaviour { // 状態 enum State { CountUp, Rotate }; [SerializeField, Range(0, 1080), Tooltip("回転速度")] int speed = 360; [SerializeField, Tooltip("状態")] State state = State.CountUp; [SerializeField, Tooltip("数値")] float time = 0; [SerializeField, Tooltip("テキスト")] UnityEngine.UI.Text timeText = null; // 回転角 Vector3 eulers; // 回転方向 Vector3 vector3 = Vector3.back; void Update() { // State.Rotate の場合 if (state == State.Rotate) { // 回転角の更新 eulers = Time.deltaTime * vector3 * speed; // ui.Text を回転させる timeText.transform.Rotate(eulers); // クリック(タップ)開始 if (Input.GetMouseButtonDown(0)) { // State.CountUp に切り替え state = State.CountUp; } } // State.CountUp の場合 else if (state == State.CountUp) { // time に deltaTime を加算 time += Time.deltaTime; // timeText を更新 timeText.text = ((int)time).ToString(); // クリック(タップ)開始 if (Input.GetMouseButtonDown(0)) { // State.Rotate に切り替え state = State.Rotate; } } } }
このままでも正常に作動しますが,2つの状態それぞれでInput.GetMouseButtonDown(0)
を検知しているのが冗長に思えます。
これを1か所で検知する事によって,コードを整理します。
列挙定数を工夫する
using UnityEngine; public class NewBehaviourScript : MonoBehaviour { // 状態 enum State { CountUp = -1, Rotate = 1 }; [SerializeField, Range(0, 1080), Tooltip("回転速度")] int speed = 360; [SerializeField, Tooltip("状態")] State state = State.CountUp; [SerializeField, Tooltip("数値")] float time = 0; [SerializeField, Tooltip("テキスト")] UnityEngine.UI.Text timeText = null; // 回転角 Vector3 eulers; // 回転方向 Vector3 vector3 = Vector3.back; void Update() { // State.Rotate の場合 if (state == State.Rotate) { // 回転角の更新 eulers = Time.deltaTime * vector3 * speed; // ui.Text を回転させる timeText.transform.Rotate(eulers); } // State.CountUp の場合 else if (state == State.CountUp) { // time に deltaTime を加算 time += Time.deltaTime; // timeText を更新 timeText.text = ((int)time).ToString(); } // クリック(タップ)開始 if (Input.GetMouseButtonDown(0)) { // State.CountUp に切り替え state = (State)((int)state * -1); } } }
列挙型State
の列挙子に,それぞれ-1
と1
という定数を割り当てました。
これによって,今の状態にかかわらずstate
に-1
を掛ける事で相互の切り替えが可能になりました。
ただし,-1
の意味が分かりにくいという欠点が有ります。
当ブログではほとんどの命令にコメントを添えていますが,コメントが無くとも理解できるコードを心掛けたいものです。
そこで,定数の出番です。
掛ける数である-1
を定数にして,役割を明確化しましょう。
定数を利用する
using UnityEngine; public class NewBehaviourScript : MonoBehaviour { // 状態 enum State { CountUp = -1, Rotate = 1 }; // 状態切り替え定数 const int Switch = -1; [SerializeField, Range(0, 1080), Tooltip("回転速度")] int speed = 360; [SerializeField, Tooltip("状態")] State state = State.CountUp; [SerializeField, Tooltip("数値")] float time = 0; [SerializeField, Tooltip("テキスト")] UnityEngine.UI.Text timeText = null; // 回転角 Vector3 eulers; // 回転方向 Vector3 vector3 = Vector3.back; void Update() { // State.Rotate の場合 if (state == State.Rotate) { // 回転角の更新 eulers = Time.deltaTime * vector3 * speed; // ui.Text を回転させる timeText.transform.Rotate(eulers); } // State.CountUp の場合 else if (state == State.CountUp) { // time に deltaTime を加算 time += Time.deltaTime; // timeText を更新 timeText.text = ((int)time).ToString(); } // クリック(タップ)開始 if (Input.GetMouseButtonDown(0)) { // state 切り替え state = (State)((int)state * Switch); } } }
Switch
という定数名によって,state
に対する操作が直感的に分かりやすくなりました。
問題点
乗算記号と定数名との相性に,違和感は残ってしまうかもしれません。
つまり,「スイッチを掛けるとはどういう事だ?」という疑問です。
それから,キャストが複雑であることも考えものです。
これが,今回の提案の限界かもしれませんね……。
あまり実用的ではないかもしれませんが,せっかく思い付いたので公開してみました。
なにか良いアイディアがございましたら,御連絡お待ちしております。
以上,2つの状態を同じ命令で切り替える方法の提案でした。