C# 如何在unity 4.6的OnBeginDrag()中停止拖动事件

C# 如何在unity 4.6的OnBeginDrag()中停止拖动事件,c#,events,unity3d,drag-and-drop,C#,Events,Unity3d,Drag And Drop,我有一个脚本,用于处理从给定插槽拖动项目和将项目拖动到给定插槽的操作。但我想添加一个函数来停止拖动特定项。我认为最好的方法是使用OnBeginDrag方法,但似乎无法找到停止/取消拖动事件本身的方法,下面是我的一些代码 public class SlotBehaviour : MonoBehaviour, IDropHandler, IPointerEnterHandler, IPointerExitHandler, IBeginDragHandler, IDragHandler, IEndDr

我有一个脚本,用于处理从给定插槽拖动项目和将项目拖动到给定插槽的操作。但我想添加一个函数来停止拖动特定项。我认为最好的方法是使用
OnBeginDrag
方法,但似乎无法找到停止/取消拖动事件本身的方法,下面是我的一些代码

public class SlotBehaviour : MonoBehaviour, IDropHandler, IPointerEnterHandler, IPointerExitHandler, IBeginDragHandler, IDragHandler, IEndDragHandler,IPointerClickHandler
{
    public void OnBeginDrag(PointerEventData eventData)
    {
        if (eventData.button != PointerEventData.InputButton.Left)
        {
            return;
        }
        if (this.Empty) return;
        var canvas = imageItem.canvas;
        if (canvas == null) return;
        GUIManager.mouseBusy = true;
        // We have clicked something that can be dragged.
        // What we want to do is create an icon for this.
        m_DraggingIcon = new GameObject("icon");

        m_DraggingIcon.transform.SetParent(canvas.transform, false);
        m_DraggingIcon.transform.SetAsLastSibling();

        var image = m_DraggingIcon.AddComponent<Image>();
        // The icon will be under the cursor.
        // We want it to be ignored by the event system.
        m_DraggingIcon.AddComponent<IgnoreRaycast>();

        image.sprite = imageItem.sprite;
        image.rectTransform.sizeDelta = imageItem.rectTransform.sizeDelta;


        m_DraggingPlane = transform as RectTransform;

        SetDraggedPosition(eventData);

    }

    public void OnDrag(PointerEventData data)
    {
        if (m_DraggingIcon != null)
            SetDraggedPosition(data);
    }

    private void SetDraggedPosition(PointerEventData data)
    {
        if (data.pointerEnter != null && data.pointerEnter.transform as RectTransform != null)
            m_DraggingPlane = data.pointerEnter.transform as RectTransform;

        var rt = m_DraggingIcon.GetComponent<RectTransform>();
        Vector3 globalMousePos;
        if (RectTransformUtility.ScreenPointToWorldPointInRectangle(m_DraggingPlane, data.position, data.pressEventCamera, out globalMousePos))
        {
            rt.position = globalMousePos;
            rt.rotation = m_DraggingPlane.rotation;
        }
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        if (m_DraggingIcon != null)
        {

            Destroy(m_DraggingIcon);
        }
        GUIManager.mouseBusy = false;
        //if you drop it somewhere where its not wanted(or just nowhere)
        if (eventData.used == false)
        {
            if (eventData.pointerCurrentRaycast.gameObject == null)// if its nowhere offer to drop it on ground
            {
                GUIManager.instance.DropItem((int)ItemsDatabase.container[containerID].items[indexInContainer]);
            }
        }
    }
}
公共类SlotBehaviour:MonoBehavior、IDropHandler、IpInterenterHandler、IpInterExitHandler、IbRegindragHandler、IDragHandler、IpInterclickHandler
{
公共void OnBeginDrag(PointerEventData事件数据)
{
if(eventData.button!=PointerEventData.InputButton.Left)
{
返回;
}
如果(本.空)返回;
var canvas=imageItem.canvas;
if(canvas==null)返回;
GUIManager.mouseBusy=true;
//我们单击了一些可以拖动的内容。
//我们要做的是为此创建一个图标。
m_DraggingIcon=新游戏对象(“图标”);
m_DraggingIcon.transform.SetParent(canvas.transform,false);
m_DraggingIcon.transform.SetAsLastSibling();
var image=m_DraggingIcon.AddComponent();
//图标将位于光标下方。
//我们希望事件系统忽略它。
m_DraggingIcon.AddComponent();
image.sprite=imageItem.sprite;
image.rectTransform.sizeDelta=imageItem.rectTransform.sizeDelta;
m_DraggingPlane=变换为矩形变换;
SetDragedPosition(事件数据);
}
公共void OnDrag(PointerEventData数据)
{
如果(m_拖动图标!=null)
设置拖动位置(数据);
}
私有void setDragedPosition(PointerEventData数据)
{
if(data.pointerEnter!=null&&data.pointerEnter.transform as RectTransform!=null)
m_DraggingPlane=data.pointerEnter.transform作为RectTransform;
var rt=m_DraggingIcon.GetComponent();
Vector3-globalMousePos;
if(RectTransformUtility.ScreenPointToWorldPointInRectangle(m_拖动平面、data.position、data.pressEventCamera、out globalMousePos))
{
rt.position=全球移动位置;
rt.rotation=m_拖动平面旋转;
}
}
公共无效OnEndRag(PointerEventData事件数据)
{
如果(m_拖动图标!=null)
{
销毁(m_DraggingIcon);
}
GUIManager.mouseBusy=false;
//如果你把它丢在不需要的地方(或者什么地方也不需要)
if(eventData.used==false)
{
if(eventData.pointercurrentrycast.gameObject==null)//如果没有任何地方愿意把它扔到地上
{
GUIManager.instance.DropItem((int)ItemsDatabase.container[containerID].items[indexInContainer]);
}
}
}
}
我之前尝试返回该方法,但它没有做任何事情,可能需要对事件数据做一些处理…如果您告诉我如何处理它,我将不胜感激。

您可以创建标志(例如,IsDragable)。对于不想拖放的项目,必须从拖动事件处理程序返回:

public class DragHangler : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {

public bool IsDragable;

#region IBeginDragHandler implementation
public void OnBeginDrag (PointerEventData eventData)
{
    if (!IsDragable)    return;

    Debug.Log ("OnBeginDrag:Do something");
}
#endregion

#region IDragHandler implementation

public void OnDrag (PointerEventData eventData)
{
    if (!IsDragable)    return;

    Debug.Log ("OnDrag: Do something");
}

#endregion

#region IEndDragHandler implementation

public void OnEndDrag (PointerEventData eventData)
{
    if (!IsDragable) return;

    Debug.Log ("OnEnd: Do something");
}

#endregion
}
另一种解决方案是禁用CanvasGroup组件中的BlockRaycast

仅使用“return”不会取消任何操作

相反,您可以修改传递到OnBeginDrag函数中的PointerEventData信息-具体地说,将pointerDrag设置为null。这将取消拖动:

eventData.pointerDrag = null;
设置null在2020年似乎不起作用:/ 警报,似乎在2020年不起作用。OnDrag仍然会被叫来

这里有一个有效的标志解决方案。注意:您必须在逻辑上使用鼠标按下?但没有其他现实的方法:/

using UnityEngine;
using UnityEngine.EventSystems;

public class CancellableDragBase : MonoBehaviour,
    IBeginDragHandler, IDragHandler, IEndDragHandler,
    IPointerUpHandler
{
    bool cancelDrag = false;

    public virtual void OnBeginDragCancellable() {}
    public virtual void OnDragCancellable() {}
    public virtual void OnEndDragCancellable() { }

    public void OnBeginDrag(PointerEventData eventData)
    {
        if (cancelDrag)
        {
            return;
        }
        OnBeginDragCancellable();
    }

    public void OnDrag(PointerEventData eventData)
    {
        if (cancelDrag)
        {
            return;
        }
        OnDragCancellable();
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        if (cancelDrag)
        {
            cancelDrag = false;
            return;
        }
        OnEndDragCancellable();
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        if (cancelDrag)
        {
            cancelDrag = false;
            return;
        }
    }

    public void CancelDragIfAny()
    {
        if (Input.GetMouseButton(0))
        {
            cancelDrag = true;
        }
        else
        {
        }
    }
}

多麻烦啊。

我就是这么做的。但这并不能真正停止对象的OnDrag和OnEndDrag事件。或者OnDrop(在目的地调用)。这里没有问题。您可以在OnDrop事件中检查IsDragable标志。如果是假的,什么也不要做。谢谢!我喜欢BlockRaycast更好的方法,因为这也会禁用依赖于该游戏对象的拖动事件的所有触发器(如动画),而DragHandler并没有帮助禁用事件并仍然触发触发(动画播放)。这并没有回答OP,它提供了一种绕过这些事件仍然被引发的事实的方法。应该是可以接受的,因为它实际上阻止了对OnDrag和OnEndDrag的进一步调用。。。因此,您不必检查其中的任何标志。注意-这里有一个非常完整、优雅的拖放解决方案。。请将此标记为正确答案。关于从事件方法返回的另一个建议是幼稚的!这个答案是在被接受的答案发布两年后发布的,但这实际上是正确的答案。如上所述,将
pointerDrag
设置为
null
实际上可以防止引发OnDrag和onendrag事件。谢谢令人沮丧的是,我发现这样做不起作用——我想知道2020年是否有bug?
eventData.pointerDrag=null在2020.1为我工作。17f1@DustinGraham ; 谢谢隐马尔可夫模型;如果鼠标还没动,这里肯定不工作。ondrag、oneddrag和onpointerup仍然被错误地调用。我会调查更多!