PCとスマホの両方で動作するタッチ(クリック)検知クラスを作成しました。
Unityのタッチ検知
Unityでクリックやタッチを検知する場合、こんな感じの処理を書きます。
// クリック(PC) if (Input.GetMouseButtonDown(0)) { // 処理 } // タッチ(スマホ) if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) { // 処理 }
これはつまり、エディタとスマホで処理を分けないといけないということです。
まあ正確には Input.GetMouseButtonDown() はスマホでも使えますが、
マルチタッチなどを考えると Input.GetTouch() を使うほうがいいでしょう。
ただ、判定するたびにいちいち処理をわけるのもあほらしい・・
というわけでそのあたりをラップするクラスを作りました。
スマホとPC両方で使えるタッチ検知クラス
#if UNITY_EDITOR #define IS_EDITOR #endif using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// TouchInput /// </summary> public class TouchInput: MonoBehaviour { /// <summary> /// シングルトン /// </summary> private static TouchInput _instance; private static TouchInput Instance { get{ if (_instance == null) { var obj = new GameObject(typeof(TouchInput).Name); _instance = obj.AddComponent<TouchInput>(); } return _instance; } } /// <summary> /// タッチ開始時のイベント /// </summary> public static event System.Action<TouchInfo> Started { add { Instance._started += value; } remove { Instance._started -= value; } } /// <summary> /// タッチ中のイベント /// </summary> public static event System.Action<TouchInfo> Moved { add { Instance._moved += value; } remove { Instance._moved -= value; } } /// <summary> /// タッチ終了時のイベント /// </summary> public static event System.Action<TouchInfo> Ended { add { Instance._ended += value; } remove { Instance._ended -= value; } } private TouchInfo _info = new TouchInfo(); private event System.Action<TouchInfo> _started; private event System.Action<TouchInfo> _moved; private event System.Action<TouchInfo> _ended; /// <summary> /// 現在のタッチ状態 /// </summary> private TouchState State { get { #if IS_EDITOR // エディタの場合の処理 if (Input.GetMouseButtonDown(0)){ return TouchState.Started; } else if (Input.GetMouseButton(0)){ return TouchState.Moved; } else if (Input.GetMouseButtonUp(0)){ return TouchState.Ended; } #else // エディタ以外の場合 if (Input.touchCount > 0) { switch (Input.GetTouch(0).phase) { case TouchPhase.Began: return TouchState.Started; case TouchPhase.Moved: case TouchPhase.Stationary: return TouchState.Moved; case TouchPhase.Canceled: case TouchPhase.Ended: return TouchState.Ended; default: break; } } #endif return TouchState.None; } } /// <summary> /// タッチされている位置 /// </summary> private Vector2 Position { get { #if IS_EDITOR return State == TouchState.None ? Vector2.zero : (Vector2)Input.mousePosition; #else return Input.GetTouch(0).position; #endif } } private void Update(){ if (State == TouchState.Started) { _info.screenPoint = Position; _info.deltaScreenPoint = Vector2.zero; if (_started != null) { _started(_info); } } else if (State == TouchState.Moved) { _info.deltaScreenPoint = Position - _info.screenPoint; _info.screenPoint = Position; if (_moved != null) { _moved(_info); } } else if (State == TouchState.Ended) { _info.deltaScreenPoint = Position - _info.screenPoint; _info.screenPoint = Position; if (_ended != null) { _ended(_info); } } else { _info.deltaScreenPoint = Vector2.zero; _info.screenPoint = Vector2.zero; } } } /// <summary> /// タッチ情報 /// </summary> public class TouchInfo{ /// <summary> /// タッチされたスクリーン座標 /// </summary> public Vector2 screenPoint; /// <summary> /// 1フレーム前にタッチされたスクリーン座標との差分 /// </summary> public Vector2 deltaScreenPoint; /// <summary> /// タッチされたビューポート座標 /// </summary> public Vector2 ViewportPoint { get { _viewportPoint.x = screenPoint.x / Screen.width; _viewportPoint.y = screenPoint.y / Screen.height; return _viewportPoint; } } /// <summary> /// 1フレーム前にタッチされたビューポート座標との差分 /// </summary> public Vector2 DeltaViewportPoint { get { _deltaViewportPoint.x = deltaScreenPoint.x / Screen.width; _deltaViewportPoint.y = deltaScreenPoint.y / Screen.height; return _deltaViewportPoint; } } private Vector2 _viewportPoint = Vector2.zero; private Vector2 _deltaViewportPoint = Vector2.zero; } /// <summary> /// タッチ状態 /// </summary> public enum TouchState{ /// <summary> /// タッチなし /// </summary> None = 0, /// <summary> /// タッチ開始 /// </summary> Started = 1, /// <summary> /// タッチ中 /// </summary> Moved = 2, /// <summary> /// タッチ終了 /// </summary> Ended = 3, }
こんな感じです。
フリックとかはもっと外側で実装すべきものとして、
タッチ開始と終了の位置、タッチ中の位置の差分が取れれば十分かなという感じ。
今回はマルチタッチには対応していません。
使い方
使い方はシンプル。
TouchInput.Started += info => { /* 処理 */ };