タッチデバイス向けの、GUI Textureでボタンを実装するテストコード。
前提条件:
複数ボタンの同時押しは考慮しない。マルチタップ時には最初のタップを処理の対象とする。
「ボタンがタップされた」は、「ボタンの上でタップが開始」されて、「ボタンの上でタップが終了」した時とする。
コードの構成と内容:
GUI Textureに追加するコード(GUIButton.cs)と全体を制御するコード(Scene.cs)の2つ。
ボタン自体の状態(画像の入れ替え、状態の遷移など)はGUIButton.csが担当する。
ボタンが押された際の振る舞いは、Scene.csが担当する。Start()で自分自身とタップされた時(OnTap)のメッセージ(メソッド名)をボタンへ設定しておく。
ボタンの状態は、プロパティbuttonStatusで取得することが出来る。
ボタンは以下の4つの状態を持つ
- UP – 何もされていない状態
- DOWN – 押されている状態(ボタンがタップされた)
- CANCEL – キャンセルされた状態(ボタンの外でタップがタップが終了した)
- END – 押下終了(ボタンの上でタップが終了した)
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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
using UnityEngine; using System.Collections; public class GUIButton : MonoBehaviour { public enum BUTTON_STATUS { NONE = -1, UP = 0, DOWN, END, CANCEL, }; public BUTTON_STATUS buttonStatus = BUTTON_STATUS.UP; private BUTTON_STATUS buttonStatusNext = BUTTON_STATUS.NONE; public Texture textureUp; public Texture textureDown; public Scene scene; public string OnTap; // Use this for initialization void Start () { } // Update is called once per frame void Update() { switch(buttonStatus) { case BUTTON_STATUS.UP: if(Input.touchCount > 0) { Touch touch = Input.GetTouch(0); if(touch.phase == TouchPhase.Began) { if(guiTexture.HitTest(touch.position)) { buttonStatusNext = BUTTON_STATUS.DOWN; } } } break; case BUTTON_STATUS.DOWN: if(Input.touchCount > 0) { Touch touch = Input.GetTouch(0); if(touch.phase == TouchPhase.Moved) { if(!guiTexture.HitTest(touch.position)) { buttonStatusNext = BUTTON_STATUS.CANCEL; } } else if(touch.phase == TouchPhase.Ended) { if(guiTexture.HitTest(touch.position)) { buttonStatusNext = BUTTON_STATUS.END; } } } break; case BUTTON_STATUS.CANCEL: buttonStatusNext = BUTTON_STATUS.UP; break; case BUTTON_STATUS.END: buttonStatusNext = BUTTON_STATUS.UP; break; } while(buttonStatusNext != BUTTON_STATUS.NONE) { buttonStatus = buttonStatusNext; buttonStatusNext = BUTTON_STATUS.NONE; switch(buttonStatus) { case BUTTON_STATUS.DOWN: print("-> BUTTON_STATUS.DOWN"); guiTexture.texture = textureDown; break; case BUTTON_STATUS.CANCEL: print("-> BUTTON_STATUS.CANCEL"); break; case BUTTON_STATUS.END: print("-> BUTTON_STATUS.END"); scene.SendMessage(OnTap); break; case BUTTON_STATUS.UP: print("-> BUTTON_STATUS.UP"); guiTexture.texture = textureUp; break; } } } } |
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 |
using UnityEngine; using System.Collections; public class Scene : MonoBehaviour { private GUIButton button1; private GUIButton button2; void Start() { button1 = GameObject.FindGameObjectWithTag("Button1").GetComponent<GUIButton>(); button1.scene = this; button1.OnTap = "OnTapButton1"; button2 = GameObject.FindGameObjectWithTag("Button2").GetComponent<GUIButton>(); button2.scene = this; button2.OnTap = "OnTapButton2"; } public void OnTapButton1() { print("OnTapButton1()"); } public void OnTapButton2() { print("OnTapButton2()"); } void Update() { print("Button1 : " + button1.buttonStatus); print("Button2 : " + button2.buttonStatus); } } |
Unity Remote で実機デバッグしていると、touchPhaseが上手く拾えないことがまれに発生する。実機転送後は問題なく動作しているので気にしなければ良いんだけど。
あえて、デバッグをスムーズに進めるために、現在はtouchPhaseを使わない方法を模索中。
タッチ周りのデバッグが効率よく出来れば、こんな苦労しなくていいんだけど。