Unity Joystick手势操作
作者:无聊
实现原因
由于制作Demo的需要,第三方的相关插件都过于重量级,所以就自己实现了一个简单的手势操作方案。
基本功能
本文实现了一个简易的Unity JoyStick手势操作,主要实现三个功能,操纵杆(Joystick)、相机旋转(Rotate)与缩放(Scale)。
基本逻辑结构如下:
protected void LateUpdate()
{
AroundByMobileInput();
}
void AroundByMobileInput()
{
if (Input.touchCount > 0 && Input.touchCount <= 2)
{
for (int i = 0; i < Input.touchCount; i++)
{
if (Input.touches[i].phase == TouchPhase.Began)
{
判断可能存在缩放操作的计时标记
如果在屏幕左半边,则初始化Joystick
记录触摸信息,包括位置、ID
如果在屏幕右半边,则初始化Rotate
记录触摸信息,包括位置、ID
计时器增加 不能操作缩放
}
else if (Input.touches[i].phase == TouchPhase.Moved || Input.touches[i].phase == TouchPhase.Stationary)
{
根据ID来执行相应操作,Joystick还是Rotate操作
计时器操作
}
else if (Input.touches[i].phase == TouchPhase.Canceled || Input.touches[i].phase == TouchPhase.Ended)
{
同样根据ID来执行最后的收尾工作
}
}
}
根据计时器的时间判断是否可以进行缩放操作 canScale
if (canScale)
{
双指缩放操作
}
}
手势操作的实现均是根据Unity提供的Input的TouchPhase来判断状态,然后三个主要功能Joystick、Rotate和Scale根据其状态和Input的Position变换等各种属性来进行操作。
下面分别列出三个主要功能,各自单独的具体代码实现。
Joystick
Joystick的实现原理是记录触摸点第一帧的初始位置,显示操纵杆背景图。然后根据之后触摸的位置与初始位置间的相对位移计算出偏移量,即是主角需要使用的位移值,显示操纵杆。最后当触摸停止时候清空数据。
public GameObject m_OnPad;// Joystick的GameObject
public Image m_Bottom;// 背景图片
public Image m_Stick;// 操纵杆图片
private Vector3 m_BeginPos = Vector2.zero;// Joystick初始化位置
private Vector2 m_CenterPos = Vector2.zero;
private Vector3 m_Dir = Vector3.zero;// 最后计算相对的偏移距离,主角需要使用的位移值
private float m_DisLimit = 1.0f;// 用于限定操纵杆在一定范围内
private int m_MoveFingerId = -1;
private bool m_HasMove = false;
protected virtual void Start()
{
m_DisLimit = m_Bottom.rectTransform.sizeDelta.x / 2;
}
protected void AroundByMobileInput()
{
if (Input.touchCount > 0 && Input.touchCount <= 2)
{
for (int i = 0; i < Input.touchCount; i++)
{
if (Input.touches[i].phase == TouchPhase.Began)
{
if (!EventSystem.current.IsPointerOverGameObject(Input.touches[i].fingerId))
{
m_MoveFingerId = Input.touches[i].fingerId;
m_BeginPos = Input.touches[i].rawPosition;
showJoyStick();
}
}
else if (Input.touches[i].phase == TouchPhase.Moved || Input.touches[i].phase == TouchPhase.Stationary)
{
if (Input.touches[i].fingerId == m_MoveFingerId)
{
setStickCenterPos(Input.touches[i].position);
}
}
else if (Input.touches[i].phase == TouchPhase.Canceled || Input.touches[i].phase == TouchPhase.Ended)
{
if (Input.touches[i].fingerId == m_MoveFingerId)
{
hideJoyStick();
m_MoveFingerId = -1;
}
}
}
}
}
Vector2 convertTouchPosToUIP