代码示例在最下面
效果如图:
Unity使用结构体Touch
定义触屏设备的输入,每一个触控点(可以理解为每一个手指)对应一个Touch
,其中主要的属性如下:
属性 | 含义 |
---|---|
fingerId | 触控点的编号,在该触控点的生命周期内(从点下到抬起)是不变的 |
phase | 触控点的状态,是一个Touch.Phase枚举,包括: Began(手指按下), Move(手指滑动), Stationary(手指已经按下且保持不动), Ended(手指抬起), Canceled(系统停止跟踪该触控点) |
position | 触控点在屏幕的坐标(屏幕坐标系) |
其他的属性参考https://docs.unity3d.com/ScriptReference/Touch.html
1.2. fingerId分配需要注意的是对于fingerId的分配,类似于下面的过程:
使用一个数组表示哪些触控点当前被激活,初始为:
[0][0][0][0][0]
其中0表示未激活,1表示已激活。每按下一个手指时,从头寻找第一个未激活的空位,把它的索引赋给fingerId,例如按下第一个手指后,数组变为:
[1][0][0][0][0]
手指①的fingerId=0,这个时候再按下第二个手指,数组变为:
[1][1][0][0][0]
手指①的fingerId=0,手指②的fingerId=1,这个时候松开第一个手指,数组变为:
[0][1][0][0][0]
手指②的fingerId不变,还是1,这时候再按下第三个手指,数组变为:
[1][1][0][0][0]
手指②的fingerId不变,还是1,把数组的0号为给手指③,因此手指③的fingerId=0
Untiy的Input类中与Touch有关的API如下:
函数 | 含义 |
---|---|
Input.TouchCount | int, 触控点数量,即当前按下的手指数 |
Input.touches | Touch[],当前所有的Touch结构体数组 |
Input.GetTouch(int index) | 返回第index个Touch,index与fingerId无关 |
Input.multiTouchEnabled{get;set;} | 是否支持多点触控 |
当存在多个摇杆时,需要控制每个摇杆对应的fingerId,这里把摇杆类命名为JoyStick,另外定义一个控制类TouchEvent用于管理Touch与JoyStick的对应关系,TouchEvent在每次Update中读取所有的Touch:
如果是新按下的就判断是否处于某个摇杆的可触发区域,如果是就绑定,并让该摇杆读取该Touch;如果是已经按下的手指就判断是否有绑定的摇杆,如果有就让该摇杆读取该Touch;如果是抬起的手指,也先判断是否有绑定并读取,然后移除这个绑定代码如下:
TouchEvent.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TouchEvent : MonoBehaviour
{
private Dictionary<int, JoyStick> id2JoyDic = new Dictionary<int, JoyStick>();//fingerId与摇杆的映射
private List<JoyStick> joyList = new List<JoyStick>();//UI上所有的摇杆
public void AddJoy(JoyStick joy)
{
joyList.Add(joy);//添加摇杆,由JoyStick在开始时调用
}
// Update is called once per frame
void Update()
{
foreach(var touch in Input.touches)//遍历所有的触控点
{
if(touch.phase == TouchPhase.Began)//有新的触控点
{
foreach(var joy in joyList)
{
if (joy.inTouchArea(touch.position) //判断是否在可触控范围内
&& !id2JoyDic.ContainsValue(joy)) //如果对应的摇杆已经有触控点就忽略
{
id2JoyDic.Add(touch.fingerId, joy);//加入新的触控点,绑定摇杆
}
}
}
if (id2JoyDic.ContainsKey(touch.fingerId))//如果该触控点已经绑定了摇杆
{
id2JoyDic[touch.fingerId].ReadTouch(touch);//读取触控 *** 作
if(touch.phase == TouchPhase.Canceled || touch.phase == TouchPhase.Ended)//已离开的触控点
{
//移除触控点
id2JoyDic.Remove(touch.fingerId);
}
}
}
}
}
3. 摇杆实现思路
摇杆就是一个大圈+一个小圈组成,并且有一个可以触发的区域,如图:
矩形白色区域代表可以开始触控的区域,当手指按下时,把大圈的位置设为Touch的position,当手指滑动时,让小圈跟着动,并且限制它相对大圈的最大距离。
代码如下:
JoyStick.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
public class JoyStick : MonoBehaviour
{
public TouchEvent touchEvent;//多点触控管理类
public bool isFixedArea = false;//摇杆位置是否固定
private RectTransform touchArea;//可以触控的范围
public RectTransform circle;//摇杆的大圈
public RectTransform point;//摇杆的小圈
private float maxOffset;//摇杆离中心的最大距离
//public float xAxis = 0;
//public float yAxis = 0;
public UnityEvent onDown,onDrag,onUp;//按下、滑动、抬起的事件
// Start is called before the first frame update
void Start()
{
if (isFixedArea)
{
touchArea = circle;//如果固定位置,则把可触控区域设为大圈的区域
}
else
{
touchArea = this.GetComponent<RectTransform>();
}
maxOffset = Mathf.Min(circle.rect.width, circle.rect.height)/2;//计算大圈的最小半径作为小圈的最大移动距离
touchEvent.AddJoy(this);//注册摇杆
}
///
/// 读取触控 *** 作,由TouchEvent调用
///
///
public void ReadTouch(Touch touch)
{
if(touch.phase == TouchPhase.Began)
{
//如果手指按下
circle.position = touch.position;//把大圈移动到手指按下的位置
onDown.Invoke();//触发按下事件
}
else if(touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary)
{
//如果手指已经按下
Vector3 prePointPos = point.position;//记录之前的位置
Vector3 offset = new Vector3(touch.position.x, touch.position.y, 0) - prePointPos;//两帧的手指偏移量
point.position += offset;//让小圈跟着动
if ((point.position - circle.position).magnitude > maxOffset)
{
point.position = circle.position + (point.position - circle.position).normalized * maxOffset;//限制摇杆的移动
}
//xAxis = offset.x / maxOffset;//计算归一化偏移量
//yAxis = offset.y / maxOffset;
//print(string.Format("xAxis: {0} -- yAxis: {1}", xAxis, yAxis));
onDrag.Invoke();//触发滑动事件
}
else if(touch.phase == TouchPhase.Ended)
{
//如果手指抬起
point.position = circle.position;//重置小圈的位置到大圈的中心
onUp.Invoke();//触发抬起事件
}
}
///
/// 判断某一点是否在可触控范围(矩形)内,由TouchEvent调用
///
///
///
public bool inTouchArea(Vector2 pos)
{
Rect rect = touchArea.rect;
rect.x += touchArea.position.x;
rect.y += touchArea.position.y;
return rect.Contains(pos);
}
public void OnDownTest()
{
print("down");
}
public void OnDragTest()
{
print("drag");
}
public void OnUpTest()
{
print("up");
}
}
4. 代码使用
把TouchEven.cst挂在任意物体上,我这里挂在了EventSystem上
每一个摇杆如图中红框所示,
三个摇杆场景如图:
把JoyStick.cs挂在Joy1上,把circle赋给circle,joy赋给point,把TouchEvent也赋好值,如图:
5. 在手机上实时调试
在手机上安装Unity Remote app,下载链接:
链接:https://pan.baidu.com/s/1moiz-4It5euHtpd86cLwgQ
提取码:z0fy
在Unity中点击edit->project settings,设置Editor,如图:
手机打开USB调试,连接电脑,然后运行,记得调整好分辨率
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)