実現目標
iOSのゲームを製作中です。
メインキャラクターPlayerに、
・「タッチAでXZ平面の移動」
・「タッチBで向きを徐々に回転」
(・「タッチCで向きを瞬間的に回転」)
を同時に動作させようとしています。
現在はタッチAとタッチBを同時実現しようとしています。
そのため、“MoveController”タグのImageと“RotateController”タグのImage、2つをキャンバスの離れた左右に貼り付け、
・“Move~”にタッチした時はタッチAとして移動
・“Rotate~”にタッチした時はタッチBとして回転
を判別させようとしています。
発生している問題
現在、Remote機能でiphone7上でテスト中です。
『移動』『回転』それぞれの動作は実現できているのですが、2つのタッチを同時にした際、
・「タッチAで移動中」にタッチBをすると「移動が停止し、回転も動作しない」
・「タッチBで回転中」にタッチAをすると「回転が停止し、移動も動作しない」
となります。後発のタッチを離すと、先発の動作が再開します。
2つのタッチが区別できずに、後発のタッチが先発の条件を塗り替えてしまっていると理解しているのですが、その通りだとして具体的に解決する方法が考えつきません。
ご教授をどうかお願いします。
問題のスクリプト
以下は、動作させるオブジェクトにアタッチしているスクリプトです。
問題があるのがどの部分か判断できず、全記述を掲載させていただきます。当たり前ですが、エラー警告は発生していません。
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.EventSystems; 5 6public class PlayerContTouchUI : MonoBehaviour { 7 8 Vector3 Movestart; 9 Vector3 Move; 10 float deltaX; 11 float deltaZ; 12 13 public float MoveMagni = 0.1f; 14 public float amountOfRotation = 1f; 15 16 Vector3 Rostart; 17 Vector3 Ro; 18 float RodeltaX; 19 20 void Start () {} 21 22 void Update () { 23 if (Input.touchCount > 0) 24 { 25 Touch[] myTouches = Input.touches; 26 for (int i = 0; i < Input.touchCount; i++) 27 { 28 Touch t = Input.GetTouch(i); 29 if (OnMoveTouchDown() == true) //“Move~”にタッチしているか 30 { 31 if (t.phase == TouchPhase.Began) 32 { 33 Movestart = myTouches[i].position; 34 } 35 36 if (t.phase == TouchPhase.Moved) 37 { 38 Move = myTouches[i].position; 39 deltaX = (Move - Movestart).x; 40 deltaZ = (Move - Movestart).y; 41 } 42 //移動動作 43 this.transform.Translate 44 (deltaX * Time.deltaTime * MoveMagni, 0f, 45 deltaZ * Time.deltaTime * MoveMagni, 46 Space.World); 47 //移動動作ここまで 48 } 49 50 if (OnRotateTouchDown() == true) //“Rotate~”にタッチしているか 51 { 52 if (t.phase == TouchPhase.Began) 53 { 54 Rostart = myTouches[i].position; 55 } 56 57 if (t.phase == TouchPhase.Moved) 58 { 59 Ro = myTouches[i].position; 60 RodeltaX = (Rostart - Ro).x; 61 } 62 //回転動作 63 transform.Rotate(Vector3.up, RodeltaX * Time.deltaTime * -amountOfRotation); 64 } 65 } 66 } 67 } 68 69 //“Move~”にタッチしているか判定 70 bool OnMoveTouchDown() 71 { 72 if (0 < Input.touchCount) 73 { 74 for (int i = 0; i < Input.touchCount; i++) 75 { 76 Touch t = Input.GetTouch(i); 77 if (t.phase == TouchPhase.Began || t.phase == TouchPhase.Moved || t.phase == TouchPhase.Stationary) 78 { 79 PointerEventData pointer = new PointerEventData(EventSystem.current); 80 pointer.position = Input.mousePosition; 81 List<RaycastResult> result = new List<RaycastResult>(); 82 EventSystem.current.RaycastAll(pointer, result); 83 84 foreach (RaycastResult raycastResult in result) 85 { 86 if (raycastResult.gameObject.tag == "MoveController") 87 { 88 return true; 89 } 90 } 91 } 92 } 93 } 94 return false; 95 } 96 97 //“Rotate~”にタッチしているか判定 上記OnMoveTouchDown()とほぼ同内容 98 bool OnRotateTouchDown() 99 { 100 if (0 < Input.touchCount) 101 { 102 for (int i = 0; i < Input.touchCount; i++) 103 { 104 Touch t = Input.GetTouch(i); 105 if (t.phase == TouchPhase.Began || t.phase == TouchPhase.Moved || t.phase == TouchPhase.Stationary) 106 { 107 PointerEventData pointer = new PointerEventData(EventSystem.current); 108 pointer.position = Input.mousePosition; 109 List<RaycastResult> result = new List<RaycastResult>(); 110 EventSystem.current.RaycastAll(pointer, result); 111 112 foreach (RaycastResult raycastResult in result) 113 { 114 if (raycastResult.gameObject.tag == "RotateController") 115 { 116 return true; 117 } 118 } 119 } 120 } 121 } 122 return false; 123 } 124}
その他に試したこと
タッチBeganとEndedでONOFFするboolを管理すれば、「後発のタッチで先発の動作が停止」することはないだろうと試しました。動作の停止はなくなりましたが、結局は条件内でタッチが混同して、移動と回転がぶっ飛ぶことになりました。
今後もタッチによる他動作が加わる余地を考えると、タッチの判別ができる記述と知識が必要だろうと思い、質問を投稿した次第です。
追記
「根本的におめーの学習が足りてないだろ」というご指摘は避けられませんので、「ここを見ろ」「あれを読め」というだけのご回答でもありがたいです。
※同一の質問で二重投稿してしまい、こちらを残し、一方を削除依頼しております。
追試スクリプト記述(1)
この記述の場合、タッチの混同が発生しました。
事例:画面左(-x)のMoveコントローラーで移動動作中、画面右(+x)のRotateコントローラーにタッチする
→対象Objが左(-x)に大きく吹っ飛ぶ+新規のデバックログMovestartを確認
→条件が一致しないはずの、後発のRotateタッチが、MoveタッチBeganとして判定されている。
C#
1//前略 2 3void Update () { 4 if (Input.touchCount > 0) 5 { 6 for (int i = 0; i < Input.touchCount; i++) 7 { 8 Touch t = Input.GetTouch(i); 9 if (OnMoveTouchDown() == true) 10 { 11 if (t.phase == TouchPhase.Began) 12 { 13 //Movestart = myTouches[i].position; //御回答の指摘と直接関係しないが下に変更 14 Movestart = t.position; 15 Debug.Log("Movestart" + Movestart); //タッチ混同を確認 16 } 17 //中略 18 } 19 20 if (OnRotateTouchDown() == true) 21 { 22 //略 23 } 24 } 25 } 26 } 27 28 bool OnMoveTouchDown() 29 { 30 if (0 < Input.touchCount) 31 { 32 for (int i = 0; i < Input.touchCount; i++) 33 { 34 Touch t = Input.GetTouch(i); 35 if (t.phase == TouchPhase.Began || t.phase == TouchPhase.Moved || t.phase == TouchPhase.Stationary) 36 { 37 PointerEventData pointer = new PointerEventData(EventSystem.current); 38 //pointer.position = Input.mousePosition; //★ご指摘の箇所★ 39 pointer.position = t.position; //上記述から変更 40 //以下、略 41 } 42 43 bool OnRotateTouchDown() 44 { 45 //OnMoveTouchDown()と同様の変更のため、略 46 } 47}
追試スクリプト記述(2)
タッチ判定の条件付けに原因があると思え、別の方式を試行。
nullがちゃんと扱えず、エラー。
C#
1//前略 2void Update() 3 { 4 //“Move~”にタッチしているか 5 Touch? t = OnMoveTouchDown(); //null許容のためにTouch?に変更 6 if (t != null) //Touch?のため、ここは通過 7 { 8 Debug.Log(t); //Touchログが出るが… 9 if (t.phase == TouchPhase.Began) //'phase'がTouch?に含まれていない.エラー 10 { 11 Movestart = t.position; //'position'同様 12 } 13 //中略 14 } 15 16 //“Rotate~”にタッチしているか 17 Touch? r = OnRotateTouchDown(); 18 if (r != null) 19 { 20 //中略 21 } 22 } 23 24Touch? OnMoveTouchDown() 25 { 26 if (0 < Input.touchCount) 27 { 28 for (int i = 0; i < Input.touchCount; i++) 29 { 30 //中略 31 if (raycastResult.gameObject.tag == "MoveController") 32 { 33 return t; 34 }}}}} 35 return null; 36 } 37 38 Touch? OnRotateTouchDown() 39 { 40 //略 41 }
解決後の記述(一部、略)
C#
1//いろいろ略 2using UnityEngine.EventSystems; 3 4 void Update() 5 { 6 if (Input.touchCount > 0) 7 { 8 for (int i = 0; i < Input.touchCount; i++) 9 { 10 Touch t = Input.GetTouch(i); 11 if (OnMoveTouchDown(t) == true) //チェック中のTouchを引数で渡す 12 { 13 if (t.phase == TouchPhase.Began) 14 { 15 Movestart = t.position; 16 } 17 if (t.phase == TouchPhase.Moved) 18 { 19 Move = t.position; 20 deltaX = (Move - Movestart).x; 21 deltaZ = (Move - Movestart).y; 22 } 23 //略 24 } 25 26 if (OnRotateTouchDown(t) == true) //チェック中のTouchを引数で渡す 27 { 28 //略 29 } 30 } 31 } 32 } 33 34 bool OnMoveTouchDown(Touch t) 35 { //当初for文を入れていたが、Update内で済ませているので不要 36 if (t.phase == TouchPhase.Began || t.phase == TouchPhase.Moved || t.phase == TouchPhase.Stationary) 37 { 38 PointerEventData pointer = new PointerEventData(EventSystem.current); 39 pointer.position = t.position; 40 List<RaycastResult> result = new List<RaycastResult>(); 41 EventSystem.current.RaycastAll(pointer, result); 42 43 foreach (RaycastResult raycastResult in result) 44 { 45 if (raycastResult.gameObject.tag == "MoveController") 46 { 47 return true; 48 } 49 } 50 } 51 return false; 52 } 53 54 bool OnRotateTouchDown(Touch t) 55 { 56 //略 57 } 58}

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/10/30 10:04
2018/10/30 13:48
2018/11/02 01:34