InputTouch
使用Unity開發的游戲大多是移動端游戲,而一些移動端游戲完全使用觸摸操作而不是點擊Button
Unity使用Input.Touch來管理觸摸操作
Input.TouchCount獲得當前觸摸的數量,這個數量多少取決於設備,通常使用觸摸之前都用這個判斷下
Input.GetTouch[index],下標決定了獲取當前觸摸點的哪一個(先后順序)
針對觸摸點,有很多狀態,由枚舉TouchPhase列出,Input.GetTouch[index].phase
TouchPhase.Began:開始觸摸時觸發,僅一次
TouchPhase.Moved:觸摸保持觸摸且移動的時候觸發,注意如果僅僅保持觸摸但是不移動,這個不會觸發
TouchPhase.Stationary:觸摸保持且靜止時觸發,和上面相反,如果不動則會觸發這個,所以是否在觸發中可以僅用TouchCount判斷或者這兩個條件同時滿足時,都代表"按住"這個狀態
TouchPhase.Ended:手指離開屏幕時觸發,僅一次
TouchPhase.Canceled:奇怪的枚舉,說是當觸摸數量超過最大時,Unity會停止追蹤觸摸而觸發
虛擬搖桿的簡單實現
通過上面的APi和狀態枚舉,虛擬搖桿將變得簡單
0:獲取當前狀態,這里加了個安卓用觸摸,編輯器用鼠標的判斷,ios一樣的
1 bool _beginTouch = false;//Update之外 2 3 //Update之內 4 bool windowsOrEditor = Application.isEditor || Application.platform != RuntimePlatform.Android; 5 bool inputDown = windowsOrEditor 6 ? (Input.GetMouseButtonDown(0) && !EventSystem.current.IsPointerOverGameObject()) 7 : (Input.touchCount > 0 && !_beginTouch && !EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)); 8 bool inputStay = windowsOrEditor 9 ? Input.GetMouseButton(0) 10 : _beginTouch && Input.touchCount > 0; 11 bool inputUp = windowsOrEditor 12 ? Input.GetMouseButtonUp(0) || !Input.GetMouseButton(0) : Input.touchCount <= 0 && _beginTouch;
1:在TouchPhase.Began狀態下,可以獲取當前點在屏幕的坐標,Input.GetTouch[index].position;,記錄為坐標起點_startPos(我這里轉到了UGUI某組件下的物體坐標系中)
1 if (inputDown)//update()中 2 { 3 //記錄初始位置 4 _beginTouch = true; 5 Vector2 pos; 6 RectTransformUtility.ScreenPointToLocalPointInRectangle(_moveTip.parent as RectTransform, 7 Input.mousePosition, null, out pos); 8 }
2:在TouchPhase.Stationary和TouchPhase.Moved(或者直接判斷TouchCount>0)狀態中,用移動后的坐標減去起點_startPos(Input.GetTouch[index].position - _startPos,順序不能變,由起點指向當前點),獲得新向量_offsetPos,可以獲得它們之間的距離(_offsetPos.magnitude,就是向量減法求模),可以根據距離大於多少后,做出之后的操作
3:同樣在2的狀態下,給起點一個默認方向_startDir,(如美術給的圖默認向下,就是vector2.down),將_offsetPos歸一化后和_startDir點乘(Vector2.Dot()),獲得向量夾角的余弦CosA,利用反余弦(Mathf.Acos()結果是弧度,需要乘Mathf.Rad2Deg轉角度)求出角度,給美術資源做旋轉Z軸即可(正向還是反向通過坐標x對比)
1 else if (inputStay) 2 { 3 Vector2 pos; 4 RectTransformUtility.ScreenPointToLocalPointInRectangle(_moveTip.parent as RectTransform, 5 Input.mousePosition, null, out pos); 6 float angleCos = Vector2.Dot((pos - _moveTip.anchoredPosition).normalized, Vector2.down); 7 float angle = Mathf.Acos(angleCos) * Mathf.Rad2Deg; 8 float dis = pos.x < _moveTip.anchoredPosition.x ? -1 : 1; 9 10 } 11 else if (inputUp) 12 { 13 _beginTouch = false; 14 }