gpt4 book ai didi

unity3d - Unity3D中OnPointerDown与OnBeginDrag的恐怖

转载 作者:行者123 更新时间:2023-12-02 11:23:44 31 4
gpt4 key购买 nike

我担心单指运动代码中OnPointerDownOnBeginDrag之间的区别。
(在最新的使用物理光线投射器的Unity范例中:因此,最终,Unity将正确忽略UI层上的触摸。
因此,从2015年开始,您必须做的是:

  • 忘了废话传统的InputTouches系统,它们是毫无意义的废话,不起作用
  • 添加一个通常为BoxCollider2D的空游戏对象,该对象可能大于屏幕。使称为“绘图”的图层。物理设置,“绘图”没有任何作用
  • 只需将2D或3D物理光线投射器添加到相机中即可。事件遮罩“绘图”层。

  • enter image description here
    像下面这样编写脚本并放上它。
    (提示-不要忘记简单地在场景中添加一个EventSystem。奇怪的是,Unity在某些情况下不会自动为您执行此操作,但在其他情况下Unity会自动为您执行此操作,因此,如果您忘记了,那会很烦人!)
    但是这是问题
    在使用OnPointerDownOnBeginDrag(以及匹配的结束调用)之间必须有一些细微的区别。 (您可以只交换以下代码示例中的操作。)
    自然,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);
    }
    }
    这是一件方便的事情。使用鲜为人知但精致的3D场景,用相同的内容保存键入内容
    pointerCurrentRaycast
    这是...如何注意到优秀
    data.pointerCurrentRaycast.worldPosition
    致电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;
    }
    }

    最佳答案

    我首先要说InputTouches并不糟糕,它们仍然有用,并且是在touchOnPointerDown出现之前在移动设备上检查OnBeginDrag的最佳方法。您可以将OnMouseDown()称为crappy,因为它并未针对移动设备进行优化。对于刚开始学习Unity的初学者,他们可以选择InputTouches
    至于您的问题,OnPointerDownOnBeginDrag,而不是。尽管它们几乎做相同的事情,但是它们被实现为以不同的方式执行。下面我将描述其中的大多数:OnPointerDown:
    当屏幕上有按下/触摸时(在触摸屏上单击或按下手指时)调用OnPointerUp:
    释放按下/触摸(释放点击或从触摸屏上移开手指)时调用OnBeginDrag:
    在开始拖动之前,将其称为一次(当手指/鼠标向下移动的第一个时间时)OnDrag:
    当用户在屏幕上拖动时(当手指/鼠标在触摸屏上移动时)反复调用OnEndDrag:
    当拖动停止时调用(当手指/鼠标不再在触摸屏上移动时,不再调用时调用)。
    OnPointerDown OnBeginDrag OnEndDrag
    如果尚未调用OnPointerUp ,则将调用,而不调用。如果尚未调用OnPointerDown ,则将调用,而不调用。就像C++,C#中的花括号一样,您打开,将其' {',然后关闭,将其'} '。
    差异:
    当手指/鼠标在触摸屏上时,OnPointerDown将被称为
    ,一旦被命名为
    ,则立即被称为
    。除非有鼠标移动或手指在屏幕上移动,否则什么都不会发生,一旦
    后跟OnDrag,则OnEndDrag将称为
    这些是为进行高级使用而设计的,例如带有未包含在Unity中的控件的自定义 UI。
    每次使用时:
    1. 当您必须执行简单单击按钮时(例如,屏幕上的向上,向下,拍摄按钮),您需要OnBeginDrag来检测触摸。这应该适用于Sprite图片。
    2. 如果您必须实现自定义切换开关,并且希望它是现实的,以便玩家可以向左/向右或向上/向下拖动到切换,则需要OnBeginDragOnPointerDownOnPointerDownOnBeginDragOnDrag。您需要以此顺序编写代码,以在屏幕上显示平滑 Sprite / Texture过渡。一些切换开关被设置为单击,它将切换。某些人喜欢通过使其变得逼真来使它看起来逼真,因此您必须拖动以便将切换到
    3. 同样,当您要实现可拖拽的通用可重用弹出窗口 时,还需要使用这5个函数(OnEndDragOnPointerUpOnPointerDownOnBeginDragOnDrag)。
    首先检测是否有一个click(OnEndDrag),检查以确保单击的Sprite是您要移动的正确的Sprite。等待玩家移动(OnPointerUp)他们的手指/鼠标。一旦他们开始拖动,也许您可​​以使用OnPointerDown调用协程函数循环,它将开始移动Sprite,并在该协程内部,您可以使用OnBeginDrag或其他任何首选方法平滑 Sprite的运动。
    由于while曾经被调用过,因此它是开始协程的好地方。
    当玩家继续拖动Sprite时,Time.deltaTime将重复称为 。使用OnBeginDrag函数获取查找器的当前位置,并将其更新为OnDrag,已运行
    的协程的协程将用于更新,将Sprite的位置更新。当播放器停止在屏幕上移动手指/鼠标的时,会调用OnDrag,您可以Vector3变量并告诉协程停止更新的Sprite位置。然后,当玩家释放手指(OnEndDrag)时,您可以使用StopCoroutine函数停止协程。
    由于有了boolean,我们可以在拖动开始后就开始协程,而等待拖动结束。 不会使成为,以来启动OnPointerUp中的协程,因为这意味着每次玩家触摸屏幕时,协程将是来启动
    没有OnBeginDrag,我们必须使用OnPointerDown变量使协程仅在每次调用的OnBeginDrag函数中启动一次,否则协程将在各处运行,并且Sprite会发生意外移动。
    4. 当您想确定玩家移动手指多长时间时。例如,著名游戏水果忍者。假设您要确定玩家在屏幕上滑动的距离。
    首先,等待直到调用boolean再次等待直到调用OnDrag,然后您可以获取OnPointerDown函数内手指的当前位置,因为在手指开始移动之前调用了OnBeginDrag。释放手指后,将调用OnBeginDrag。然后,您可以再次获取手指的当前位置。您可以使用这两个
    位置
    来检查减去后手指移动了多远。
    如果您决定使用OnBeginDrag作为获取手指的第一个 位置的位置,则会得到错误的结果,因为如果播放器向右滑动,则会向左滑动 再次等待,然后向上滑动 ,而在每次滑动之后不松开手指,唯一的良好结果是第一次滑动(正确的swipe)。左侧
    上的和向上滑动将具有无效的值,因为在OnEndDrag时获得的第一个值称为,是您仍在上使用的值。这是因为玩家从未将手指从屏幕上移开,因此因此OnPointerDown不再是,从再也称为,不再是
    ,并且第一个旧旧值仍然存在。
    但是,当您使用OnPointerDown而不是OnPointerDown时,此问题将变成消失了,因为当手指停止移动时,将调用OnBeginDrag,并在其再次开始移动时再次调用OnPointerDown,从而导致第一个位置覆盖使用新的

    关于unity3d - Unity3D中OnPointerDown与OnBeginDrag的恐怖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36048106/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com