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仍然被错误地调用。我会调查更多!