この記事でのバージョン
Unity 2019.2.21f1
はじめに
Unityはマウスのクリックやスマホでのタッチを簡単に取得する事できます。
private void Update(){ if (Input.GetMouseButton(0)) { Debug.Log("マウスのクリック発生中"); } if (Input.touchCount > 0) { Debug.Log("タッチ発生中"); } }
ただ、uGUIのボタン等と被っていると両方のイベントが同時に発生してしまいます。
今回はそんな時にuGUIの操作を優先する実装方法の紹介です!
なお、記事中の画像は以下のアセットを使っております。
2D Medieval Fantasy Character Pack | 2D Characters | Unity Asset Store |
IsPointerOverGameObject
まずuGUIのタッチ等のイベントはEventSystemで管理されています。
そしてこのEventSystemにはIsPointerOverGameObjectという、
uGUIのオブジェクトを選択しているかというフラグがあります。
これを使えばuGUIのボタン等を押しているかが分かるので、
そういう場合はマウスのクリックやタッチを無視すれば、uGUIの操作を優先できます。
具体的には以下のような感じ。
/*EventSystemを使うにはusing UnityEngine.EventSystems;が必要*/ private void Update(){ //UIを触ってる場合はスルー if(EventSystem.current.IsPointerOverGameObject()){ return; } //スマホなどのタッチの場合の判定 if (Input.touchCount > 0){ if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)){ return; } } if (Input.GetMouseButton(0)) { Debug.Log("マウスのクリック発生中"); } if (Input.touchCount > 0) { Debug.Log("タッチ発生中"); } }
Event Trigger
もしSprite Rendererのクリック判定を実装したいのでRaycastを使ってる場合でも、
IsPointerOverGameObjectでuGUIを優先する実装は出来ますが、
private void Update(){ //UIを触ってる場合はスルー if(EventSystem.current.IsPointerOverGameObject()){ return; } //スマホなどのタッチの場合の判定 if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began){ if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)){ return; } } //クリック or タッチが発生しているか判定、している場合はその座標を取得 Vector2 clickOrTouchingPosition; if (Input.GetMouseButton(0)) { clickOrTouchingPosition = Input.mousePosition; } else if (Input.touchCount > 0) { clickOrTouchingPosition = Input.GetTouch(0).position; } else { return; } //メインカメラ上からRayを飛ばす Ray ray = Camera.main.ScreenPointToRay(clickOrTouchingPosition); RaycastHit2D hit = Physics2D.Raycast((Vector2)ray.origin, (Vector2)ray.direction); //レイが何かと衝突したかの判定 if(hit.collider == null) { Debug.LogWarning("クリックした所に何もありません"); } else { Debug.Log($"{hit.collider.gameObject.name}をクリック中"); } }
こういう時はカメラにPhysics 2D Raycasterを付けた後、
Sprite Rendererと同じオブジェクトにEvent Triggerを付けて、
そこにクリックした時の処理を登録すると、
先程のUpdateの処理なしで実装出来るのでオススメです。
/// <summary> /// キャラクターが押された時の処理 /// </summary> public void OnClickCharacter(GameObject target) { Debug.Log($"{target.name}が押されました"); } /// <summary> /// ボタンが押されました /// </summary> public void OnClickButton() { Debug.Log("ボタンが押されました"); }
参考