Fat*_*tie 4 touch unity-game-engine unity3d-ui
我担心单指移动代码OnPointerDown与之间的区别OnBeginDrag.
(在使用物理raycaster的最新Unity范例中:最后,Unity将正确地忽略UI层上的触摸.
所以从2015年开始你必须做的是:
忘记垃圾传统Input或Touches系统废话甚至Unity承认是完全没有意义的废话 - 因为他们不工作
添加一个空的游戏对象,通常是BoxCollider2D,可能比屏幕大.使图层"绘制"(物理设置,它与任何东西互动)
只需添加到相机,2D或3D物理raycaster.事件掩盖你的"绘图"图层.
做一个像下面这样的脚本并把它放在"画画"上.
(提示 - 不要忘记简单地添加一个EventSystem场景.奇怪的是,Unity在某些情况下不会自动为你做这件事,但Unity会在其他情况下自动为你做这件事,所以如果你忘记了它会很烦人!)
但这是问题所在.
在使用OnPointerDownvs OnBeginDrag(和匹配的结束调用)之间必须有一些细微的差别.(您可以在以下代码示例中交换操作.)
Unity自然没有提供任何指导; 下面的代码精美地拒绝了流浪抓取并且完美地忽略了你的UI层(感谢Unity!最后!)但是我对这两种方法之间的区别(开始拖动V开始触摸)完全神秘化了,我无论如何都找不到逻辑区别在单元测试中两者之间.
答案是什么?
/*
general movement of something by a finger.
*/
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
public class FingerMove:MonoBehaviour,
IPointerDownHandler,
IBeginDragHandler,
IDragHandler,
IPointerUpHandler,
IEndDragHandler
{
public Transform moveThis;
private Camera theCam;
private FourLimits thingLimits;
private Vector3 prevPointWorldSpace;
private Vector3 thisPointWorldSpace;
private Vector3 realWorldTravel;
public void Awake()
{
theCam = Camera.main or whatever;
}
public void OnMarkersReady() // (would be EVENT DRIVEN for liveness)
{
thingLimits = Grid.liveMarkers. your motion limits
}
private int drawFinger;
private bool drawFingerAlreadyDown;
public void OnPointerDown (PointerEventData data)
{
Debug.Log(" P DOWN " +data.pointerId.ToString() );
}
public void OnBeginDrag (PointerEventData data)
{
Debug.Log(" BEGIN DRAG " +data.pointerId.ToString() );
if (drawFingerAlreadyDown == true)
{
Debug.Log(" IGNORE THAT DOWN! " +data.pointerId.ToString() );
return;
}
drawFinger = data.pointerId;
drawFingerAlreadyDown=true;
prevPointWorldSpace = theCam.ScreenToWorldPoint( data.position );
}
public void OnDrag (PointerEventData data)
{
Debug.Log(" ON DRAG " +data.pointerId.ToString() );
if (drawFingerAlreadyDown == false)
{
Debug.Log(" IGNORE THAT PHANTOM! " +data.pointerId.ToString() );
}
if ( drawFinger != data.pointerId )
{
Debug.Log(" IGNORE THAT DRAG! " +data.pointerId.ToString() );
return;
}
thisPointWorldSpace = theCam.ScreenToWorldPoint( data.position );
realWorldTravel = thisPointWorldSpace - prevPointWorldSpace;
_processRealWorldtravel();
prevPointWorldSpace = thisPointWorldSpace;
}
public void OnEndDrag (PointerEventData data)
{
Debug.Log(" END DRAG " +data.pointerId.ToString() );
if ( drawFinger != data.pointerId )
{
Debug.Log(" IGNORE THAT UP! " +data.pointerId.ToString() );
return;
}
drawFingerAlreadyDown = false;
}
public void OnPointerUp (PointerEventData data)
{
Debug.Log(" P UP " +data.pointerId.ToString() );
}
private void _processRealWorldtravel()
{
if ( Grid. your pause concept .Paused ) return;
// potential new position...
Vector3 pot = moveThis.position + realWorldTravel;
// almost always, squeeze to a limits box...
// (whether the live screen size, or some other box)
if (pot.x < thingLimits.left) pot.x = thingLimits.left;
if (pot.y > thingLimits.top) pot.y = thingLimits.top;
if (pot.x > thingLimits.right) pot.x = thingLimits.right;
if (pot.y < thingLimits.bottom) pot.y = thingLimits.bottom;
// kinematic ... moveThis.position = pot;
// or
// if pushing around physics bodies ... rigidbody.MovePosition(pot);
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个方便的事情.使用鲜为人知但精致的3D场景保存输入相同的内容
这是怎么...注意到优秀
data.pointerCurrentRaycast.worldPosition
Run Code Online (Sandbox Code Playgroud)
打电话给Unity.
public class FingerDrag .. for 3D scenes:MonoBehaviour,
IPointerDownHandler,
IDragHandler,
IPointerUpHandler
{
public Transform moveMe;
private Vector3 prevPointWorldSpace;
private Vector3 thisPointWorldSpace;
private Vector3 realWorldTravel;
private int drawFinger;
private bool drawFingerAlreadyDown;
public void OnPointerDown (PointerEventData data)
{
if (drawFingerAlreadyDown == true)
return;
drawFinger = data.pointerId;
drawFingerAlreadyDown=true;
prevPointWorldSpace = data.pointerCurrentRaycast.worldPosition;
// in this example we'll put it under finger control...
moveMe.GetComponent<Rigidbody>().isKinematic = false;
}
public void OnDrag (PointerEventData data)
{
if (drawFingerAlreadyDown == false)
return;
if ( drawFinger != data.pointerId )
return;
thisPointWorldSpace = data.pointerCurrentRaycast.worldPosition;
realWorldTravel = thisPointWorldSpace - prevPointWorldSpace;
_processRealWorldtravel();
prevPointWorldSpace = thisPointWorldSpace;
}
public void OnPointerUp (PointerEventData data)
{
if ( drawFinger != data.pointerId )
return;
drawFingerAlreadyDown = false;
moveMe.GetComponent<Rigidbody>().isKinematic = false;
moveMe = null;
}
private void _processRealWorldtravel()
{
Vector3 pot = moveMe.position;
pot.x += realWorldTravel.x;
pot.y += realWorldTravel.y;
moveMe.position = pot;
}
}
Run Code Online (Sandbox Code Playgroud)
Pro*_*mer 18
我想通过说开始Input并Touches没有crappy.They仍然有用的并且是检查的最佳方式touch在移动设备上之前OnPointerDown和OnBeginDrag走了过来.OnMouseDown()你可以打电话给蹩脚,因为它没有针对手机进行优化.对于初学者谁刚开始学习团结,Input并且Touches是他们的选择.
至于你的问题,OnPointerDown并且OnBeginDrag是不是的,相同的.虽然他们几乎做同样的事情,但他们被实施以不同的方式执行.下面我将介绍其中的大部分内容:
OnPointerDown:当屏幕上有按下/触摸时(在触摸屏上按下咔嗒声或手指时)调用
OnPointerUp:释放按下/触摸时(释放单击或从触摸屏移除手指时调用)
OnBeginDrag:在拖动开始之前调用一次(当手指/鼠标第一次移动时向下移动)
OnDrag :当用户在屏幕上拖动时(手指/鼠标在触摸屏上移动时)反复调用
OnEndDrag:当拖动停止时(当手指/鼠标不再在触摸屏上移动时调用).
OnPointerDown对比OnBeginDrag和OnEndDrag
OnPointerUp将不若叫OnPointerDown 尚未调用.OnEndDrag将不若叫OnBeginDrag 尚未调用.就像C++,C#中的花括号一样,你将它打开 ' { '并关闭它' } '.
的差异性:OnPointerDown将被调用一次,并立即当手指/鼠标在触摸屏上.在鼠标移动或手指在屏幕上移动之后,其他任何事情都不会发生,然后OnBeginDrag会被OnDrag 调用一次.
这些用于执行高级用法,例如具有未包含在Unity中的控件的自定义 UI.
什么时候使用每个:
1.当您必须在屏幕上实现简单的单击按钮(例如,向上,向下,拍摄按钮)时,您只需要OnPointerDown检测触摸.这适用于Sprite Images.
2.当你要实现自定义切换开关,你希望它是真实的,这样玩家可以拖动左/右或向上/向下拨动它,那么你需要的OnPointerDown, OnBeginDrag,OnDrag,OnEndDrag,OnPointerUp.您需要按此顺序编写代码,以在屏幕上实现平滑的 Sprite/Texture转换.一些切换开关被点击,它将切换.有些人喜欢通过制作它使它看起来很逼真,所以你必须拖动它才能切换它.
3.此外,当你想实现一个通用的可重复使用的弹出窗口可拖动,你还需要使用这些5个功能(OnPointerDown, OnBeginDrag,OnDrag,OnEndDrag,OnPointerUp).首先检测何时有click(OnPointerDown),检查以确保单击的Sprite是您要移动的正确的Sprite.等待玩家移动(OnBeginDrag)他们的手指/鼠标.一旦他们开始拖动,也许你可以使用while 循环来调用一个coroutine函数,它将开始移动Sprite并在该coroutine中,你可以使用或任何其他首选方法平滑 Sprite的移动Time.deltaTime.
由于OnBeginDrag被调用一次,它是一个很好的地方开始的协同程序.随着玩家继续拖动Sprite,OnDrag将被重复调用.使用该OnDrag函数获取finder的当前位置,并将其更新Vector3为已运行的coroutine 将用于更新 Sprite 的位置.当玩家停止在屏幕上移动他们的手指/鼠标时,OnEndDrag会调用并且您可以boolean变量并告诉协程停止更新 Sprite的位置.然后,当玩家释放他们的手指(OnPointerUp)时,您可以使用StopCoroutine功能停止协程.
因为OnBeginDrag我们能够在等待拖动结束时一旦拖动就开始协程.它不会使感,以启动该协程中OnPointerDown,因为这意味着每当玩家触摸屏,协同程序将启动.
如果没有OnBeginDrag,我们必须使用boolean变量使coroutine在OnDrag每次调用的函数中只启动一次,否则会在各处运行coroutine并且会发生Sprite的意外移动.
4.当你想确定玩家移动手指的时间.这个例子就是名为Fruit Ninja的着名游戏.让我们说你想确定玩家在屏幕上滑动的距离.
首先,等待直到OnPointerDown被调用,等待直到再次OnBeginDrag被调用,那么就可以得到当前内手指的位置OnBeginDrag功能,因为OnBeginDrag手指开始移动之前被调用.手指松开后, OnEndDrag被叫.然后你可以再次获得手指的当前位置.您可以使用这两个 位置通过减去它们来检查手指移动的距离.
如果您决定使用OnPointerDown作为获取手指第一个 位置的地方,您将得到错误的结果,因为如果玩家向右滑动,然后等待并向左滑动然后再次等待并在每次滑动后向上滑动 而不释放他们的手指,你唯一的好结果就是第一次滑动(向右滑动).在左边和向上轻扫将有无效的值,因为你有当第一个值被称为是你的价值仍在使用.这是因为玩家永远不会被删除从屏幕上手指这么因此,是从来没有叫一次和第一旧旧的价值仍然存在.OnPointerDownOnPointerDown
但是,当你使用OnBeginDrag,而不是OnPointerDown,这个问题会消失,因为当手指停止移动,OnEndDrag被调用,它再次开始转动时,OnBeginDrag 被称为再次导致第一位置将覆盖与新的.
| 归档时间: |
|
| 查看次数: |
12969 次 |
| 最近记录: |