OnMouseDown / OnMouseUp / OnMouseDrag はオブジェクトがマウスクリックされても、画面タップされても呼び出されるとても使い勝手のいい関数。
ただしCanvasでポップアップなんかを出しているとボタンを押してもオブジェクトに伝播してしまう。
その対策メモ。
EventSystemを使って以下のように書ける。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
void OnMouseDown() { //ボタンとかクリックされていたら無効にする if(EventSystem.current.currentSelectedGameObject != null){ return; } //ImageとかTextでも被っていれば無効にする(マウスクリック) if(EventSystem.current.IsPointerOverGameObject()){ return; } //ImageとかTextでも被っていれば無効にする(タップ) if(Input.touchCount>0&&EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)){ return; } //処理本体 //... } |
これでUnityエディタでもAndroidでも期待通りに動く。
こんな感じで処理すれば良いと思う。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
bool isOver(){ if(EventSystem.current.currentSelectedGameObject != null){ return true; } if(EventSystem.current.IsPointerOverGameObject()){ return true; } if(Input.touchCount>0&&EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)){ return true; } return false; } void OnMouseDown() { if(isOver())return; //処理 } void OnMouseUp() { if(isOver())return; //処理 } void OnMouseDrag() { if(isOver())return; //処理 } |
追記:ドラッグを伴う処理はマウスダウンありきだからコッチの方がいいかも。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
bool isOver(){ if(EventSystem.current.currentSelectedGameObject != null){ return true; } if(EventSystem.current.IsPointerOverGameObject()){ return true; } if(Input.touchCount>0&&EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)){ return true; } return false; } bool isDown=false; void OnMouseDown() { if(isOver())return; else isDown=true; //処理 } void OnMouseUp() { if(!isDown) return; else isDown=false; //処理 } void OnMouseDrag() { if(!isDown)return; //処理 } |
さらに追記:これらのスクリプトでも偶に実機ですり抜ける。
調べてると色々試している記事を発見。
これ見て確かめてみると IsPointerOverGameObject が変だった。
この現象の対応策は見つからなかったけど、現状やりたいことに合わせてUIオブジェクトにSelectableコンポーネントを追加することにした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
bool isOver(){ ... } bool isDown=false; IEnumerator Judge(){ yield return new WaitForEndOfFrame(); if(isOver())yield break; else isDown=true; //処理 } void OnMouseDown() { StartCoroutine(Judge()); } void OnMouseUp() { if(!isDown) return; else isDown=false; //処理 } void OnMouseDrag() { if(!isDown)return; //処理 } |
これだと currentSelectedGameObject の判定に引っかかるので失敗しない。
実行順序によると思うけどコルーチンを使わないとSelectableが機能しない。