Unity UGUI 怎么测试鸡爪有几个指头头同时点下

2427人阅读
Unity3D(35)
这里的多点触摸实现方式具有通用性,在提供触摸事件调用和触摸点数据的情况下都可实现。首先,我们需要继承复写ScrollRect的OnDrag方法,让其在一个触摸点的情况下,使用原有拖拽功能,在两个点的情况下,滑动缩放。
private int touchNum = 0;
public override void OnBeginDrag (PointerEventData eventData)
if(Input.touchCount & 1)
base.OnBeginDrag(eventData);
public override void OnDrag (PointerEventData eventData)
if (Input.touchCount & 1)
touchNum = Input.touchC
else if(Input.touchCount == 1 && touchNum & 1)
touchNum = Input.touchC
base.OnBeginDrag(eventData);
base.OnDrag(eventData);
使用unity自己的触摸判断,Input.touchCount,在正常情况下调用SrollRect自己的方法处理。否则,执行自己的处理。OnDrag中touchCout从多个变回一个的时候,我们首先需要调用一下OnBeginDrag,然后下一帧在执行一个点的逻辑。在实测用,这是为了解决从多个点变回一个点,但这个点是后触摸的点,会造成跳动的问题。
多点滑动的逻辑是写在Update方法里面。经过测试,发现如果写在OnDrag方法里面。会出现放到最大继续快速滑动,或是最小在快速缩小,出现突然缩放的情况。而实际上应该不能继续放大或缩小。
private float preX;
private float preY;
private void Update()
if (Input.touchCount == 2)
= Input.GetTouch(0);
= Input.GetTouch(1);
Vector3 p1
Vector3 p2
newX = Mathf.Abs(p1.x - p2.x);
newY = Mathf.Abs(p1.y - p2.y);
if (t1.phase == TouchPhase.Began || t2.phase == TouchPhase.Began)
preX = newX;
preY = newY;
else if (t1.phase == TouchPhase.Moved && t2.phase == TouchPhase.Moved)
RectTransform rt
scale = (newX + newY - preX - preY) / (rt.rect.width * 0.25f) + rt.localScale.x;
if (scale & 1.0f && scale & 2.5f)
float ratio
= scale / rt.localScale.x;
rt.localScale = new Vector3(scale, scale, 0);
float maxX
= base.content.rect.width
* scale / 2 - this.viewRect.rect.width
float minX
float maxY
= base.content.rect.height * scale / 2 - this.viewRect.rect.height / 2;
float minY
Vector3 pos
= rt.position *
if (pos.x & maxX)
pos.x = maxX;
else if (pos.x & minX)
pos.x = minX;
if (pos.y & maxY)
pos.y = maxY;
else if (pos.y & minY)
pos.y = minY;
rt.position =
preX = newX;
preY = newY;
float newX = Mathf.Abs(p1.x - p2.x);
float newY = Mathf.Abs(p1.y - p2.y);
这里我们计算的是两个触摸点坐标差值的绝对值。用来粗略的判断两个点的位置关系。
t1.phase == TouchPhase.Began || t2.phase == TouchPhase.Began
这个条件判断是为了,在移动条件达成时候,初始化前一个坐标点的数据。
float scale = (newX + newY - preX - preY) / (rt.rect.width * 0.25f) + rt.localScale.x;
这是一个粗略的判断算法。用新的xy差值减去上次的xy差值,这个结果反映了两个手指的距离变化。然后除以rt.rect.width,得到这个距离变化与缩放目标宽度的比例。0.25f是一个调整系数,用来控制scale的变化率。这里的数值就是根据手势得到的缩放率,然后加上原有的缩放数值,得到的scale就是最终需要缩放的数值。
scale & 1.0f && scale & 2.5f
这个条件约束了,最终的缩放的范围。
后面的算法,做了两个事情。
设置最终的缩放,然后计算边界的约束,让缩放后位置仍然在边界内。不然,我放大拖到边界,然后缩小就会越界的情况。
根据缩放的倍率,来设置新的位置。比如,原有位置不在00点,缩放了,那么位置也缩放同一个倍率,就能让缩放中心同步出现在手势操作位置上,而不是物体中心。
float ratio
= scale / rt.localScale.x;
这里新的缩放值除以原有缩放值,得到的就是缩放的倍率。
Vector3 pos = rt.position *
用原有的位置坐标乘以缩放倍率,得到新的位置。
float maxX = base.content.rect.width * scale / 2 - this.viewRect.rect.width / 2;
float minX = -maxX;
float maxY = base.content.rect.height * scale / 2 - this.viewRect.rect.height / 2;
float minY = -maxY;
这里是计算位置的边界。
if (pos.x & maxX) {
pos.x = maxX;
} else if (pos.x & minX) {
pos.x = minX;
if (pos.y & maxY) {
pos.y = maxY;
else if (pos.y & minY)
pos.y = minY;
rt.position =
根据边界计算新的位置坐标。UGUI 如何判断鼠标或者手指是否点击在UI上?
Rains卍Soft
比如战斗场景,UI和3D场景同时都需要响应触摸事件,如果同时响应可能就会出现触摸UI的时候影响到了3D部分。为了解决这个问题在判断3D响应之前要先判断手指是否点击在UI上。 以前NGUI的时候都是自己来发送射线判断,现在UGUI好了系统提供了更为简便的方法。
[csharp]&&
&这里我们直接在使用Input.GetMouseButtonDown(0)的地方加了一个检测函数,CheckGuiRaycastObjects,如下
[csharp]&&
不过在使用时需要先获取两个加粗显示的变量,graphicRaycaster和eventSystem。
这两个变量分别对应的是Canvas中的GraphicRaycaster组件,和创建UI时自动生成的&EventSystem&中的EventSystem组件,用的是自己制定以下就可以。
然后在使用的时候可以这样
void Update ()&
& & if (CheckGuiRaycastObjects())
& & //Debug.Log(EventSystem.current.gameObject.name);
& & if (Input.GetMouseButtonDown(0))
& & & & Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
& & & & RaycastH
& & & & if (Physics.Raycast(ray, out hit))
& & & & & & //do some thing
还有一个需要注意的地方就是,在做UI的时候一般会用一个Panel做跟目录,这个panel也会被添加到GraphicRegistry中的公共列表中,如果是这样的话记得把list.Count&0改成list.Count&1,或者直接删除Panel上的继承自Graphic的组件。
这样在结合着EventSystem.current.IsPointerOverGameObject()来使用就比较好了。
写个例子:
[csharp]&&
<font color="#-30<font color="#-29<font color="#-28<font color="#-28<font color="#-28<font color="#-28<font color="#-22<font color="#-26<font color="#-26<font color="#-26
早在去年7月份,为了让 VR/AR 应用开发人员更轻松地创建和更直观地看到 3D 虚拟对象,...
想知道在Unity中如何将游戏中角色对话的唇型与面部微表情达到次时代的水准吗?想知道...
近日,RLTY CHK工作室的联合创始人Nick Robinson发布了一篇文章,以媒体天师麦克卢汉...
VR设计师和开发者们开始着手如何让VR环境及体验更加有趣、逼真。以下是一些关于如何为room...
笔者在为《幻想装置》和《工作模拟》制作出混合现实的预告片以后,研究了更深层次的VR...博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)3409人阅读
Unity3D(35)
UGUI中ScrollRect本来是用来做水平和垂直的滑动列表的。并且内置了惯性滑动和边界弹性限制。但经过一些设置,完全可以用来做一个可以拖动的地图功能。首先,介绍一下属性的意思。
这是ScrollRect显示内容的实际区域。
Horizontal:
是否可以水平滚动
是否可以垂直滚动
MovementType:
运动到边界的限制类型, 有不限制,弹性,限制三种
是否有 滑动的惯性
DecelerationRate: 惯性减速率
ScrollSensitivity:
滚动敏感度
可是区域的大小
还有2个是水平和垂直的滚动条,做地图的话不需要显示。
如果用来制作地图,基本思路是。让ScroolRect可以水平和垂直滑动,惯性衰减运动和滑动敏感度可以直接使用,边界限制使用Clamped就是边界严格限制。最重要的是,Content设置为地图的真实大小比如 3000 * 30000的组件,而可视区域的大小就是屏幕的大小。这样地图就能够在屏幕区域内容易拖动。
如果还需要给地图增加多点触摸缩放的功能,就需要复写ScrollRect来处理。如下一个完整可以使用的封装:
using UnityE
using System.C
using UnityEngine.UI;
using UnityEngine.EventS
namespace Framework
public class MyScrollRect : ScrollRect
private int touchNum = 0;
public override void OnBeginDrag (PointerEventData eventData)
if(Input.touchCount & 1)
base.OnBeginDrag(eventData);
public override void OnDrag (PointerEventData eventData)
if (Input.touchCount & 1)
touchNum = Input.touchC
else if(Input.touchCount == 1 && touchNum & 1)
touchNum = Input.touchC
base.OnBeginDrag(eventData);
base.OnDrag(eventData);
private float preX;
private float preY;
void Update()
if (Input.touchCount == 2)
= Input.GetTouch(0);
= Input.GetTouch(1);
Vector3 p1
Vector3 p2
newX = Mathf.Abs(p1.x - p2.x);
newY = Mathf.Abs(p1.y - p2.y);
if (t2.phase == TouchPhase.Began)
preX = newX;
preY = newY;
else if (t1.phase == TouchPhase.Moved && t2.phase == TouchPhase.Moved)
RectTransform rt
scale = (newX + newY - preX - preY) / (rt.rect.width * 0.9f) + rt.localScale.x;
if (scale & 1 && scale & 3)
rt.localScale = new Vector3(scale, scale, 0);
float maxX
= base.content.rect.width
* scale / 2 - base.viewport.rect.width
float minX
float maxY
= base.content.rect.height * scale / 2 - base.viewport.rect.height / 2;
float minY
Vector3 pos
if (pos.x & maxX)
pos.x = maxX;
else if (pos.x & minX)
pos.x = minX;
if (pos.y & maxY)
pos.y = maxY;
else if (pos.y & minY)
pos.y = minY;
rt.position =
preX = newX;
preY = newY;
思路是,多点触摸我们使用系统的Input来获得数值,在update函数中不断的检测触摸。 然后重写父类的OnBeginDrag和OnDrag,在多点触摸的时候不触发,单点拖动的时候在调用父类的函数。
多点触摸缩放,主要使用两个触摸点的变化量,来给地图内容区域做缩放,并且注意在边界的时候缩放需要同步检测最大最小编辑位置,放置出现地图区域小于屏幕的情况。博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)}

我要回帖

更多关于 鸡爪几个指头 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信