[Unity]关于Unity中的触摸类Input.Touch以及简单的虚拟摇杆实现
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 }