在Unity中实现屏幕输入方向(例如摇杆),一般会用到 Input 类来获取触摸点的屏幕位置,然后根据触摸点的位置变动,计算出输入方向。 但是会存在一个问题,如果游戏界面中有按钮,对按钮的点击事件,也会影响到Input 的触摸点输入,我们希望能避免这个问题。
一个比较好的实现方案就是,不使用Input,而是使用UGUI的触摸事件。
这个方案比较简单,新建一个DirectionInput 继承MonoBehaviour,并且继承IPointerDownHandler,IPointerUpHandler,IDragHandler 三个接口。然后在代码中实现 OnPointerDown,OnDrag,OnPointerUp三个方法。
具体代码如下,可以在其他模块中,读取该对象的direction字段来获取方向。
using UnityEngine;
using UnityEngine.EventSystems;
/// <summary>
/// 玩家屏幕方向输入
/// </summary>
public class DirectionInput : MonoBehaviour ,IPointerDownHandler,IPointerUpHandler,IDragHandler
{
private const float MIN_MOVE_DISTANCE = 30f;
public static DirectionInput Instance = null;
public bool enableTouch = true;
public bool isTouching = false;
public Vector3 direction=Vector3.zero;
private Vector2 touchBeginPos, touchEndPos;
private void Awake()
{
Instance = this;
Init();
}
public void Init()
{
Input.multiTouchEnabled = false;
}
private bool IsCanTouch()
{
return enableTouch;
}
void Update()
{
if(!enableTouch){
return;
}
#if UNITY_EDITOR
KeyBoardInput();
#endif
}
/// <summary>
/// 获取键盘方向输入
/// </summary>
private void KeyBoardInput(){
#if UNITY_EDITOR
if(isTouching== true) {
return;
}
Vector3 dir = Vector3.zero;
bool keyTouch = false;
if(Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow)){
dir+= Vector3.forward;
keyTouch = true;
}
if(Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow)){
dir+= Vector3.left;
keyTouch = true;
}
if(Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow)){
dir+= Vector3.right;
keyTouch = true;
}
if(Input.GetKey(KeyCode.S)|| Input.GetKey(KeyCode.DownArrow) ){
dir+= Vector3.back;
keyTouch = true;
}
direction = dir;
#endif
}
public void OnPointerDown(PointerEventData data){
isTouching = true;
touchBeginPos = (data.position);
}
public void OnDrag (PointerEventData eventData)
{
if (!isTouching)
return;
touchEndPos = (eventData.position);
Vector2 dir = (touchEndPos - touchBeginPos).normalized;
direction.x = dir.x;
direction.y=0;
direction.z = dir.y;
//Debug.Log(touchBeginPos.ToString() +" "+touchEndPos.ToString()+" Dir:"+direction.ToString());
}
public void OnPointerUp(PointerEventData data){
isTouching = false;
}
}