参考了一下Unity官方出的Unity Samples UI例子,尝试完成UI拖拽功能。
1.首先模拟一个简单的物品拖拽的菜单:
2、然后在准备拖拽的Image1和Image2上添加同一个脚本:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class TestForDrag : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler, IDropHandler
{
//创建一个Gameobject作为拖拽时被拖拽对象的代替品
private GameObject drag_icon;
//Box1和Box3里的Image拖拽给他 Box2空的
public GameObject drag_icon2;
private void Start()
{
}
public void OnDrag(PointerEventData eventData)
{
//并将拖拽时的坐标给予被拖拽对象的代替品
Vector3 pos;
if (RectTransformUtility.ScreenPointToWorldPointInRectangle(drag_icon.GetComponent<RectTransform>(),
eventData.position, Camera.main, out pos))
{
drag_icon.transform.position = pos;
}
}
public void OnBeginDrag(PointerEventData eventData)
{
//代替品实例化
drag_icon = new GameObject("icon");
drag_icon.transform.SetParent(GameObject.Find("Canvas").transform, false);
drag_icon.AddComponent<RectTransform>();
var img = drag_icon.AddComponent<Image>();
img.sprite = this.GetComponent<Image>().sprite;
//防止拖拽结束时,代替品挡住了准备覆盖的对象而使得 OnDrop() 无效
CanvasGroup group = drag_icon.AddComponent<CanvasGroup>();
group.blocksRaycasts = false;
}
public void OnEndDrag(PointerEventData eventData)
{
//拖拽结束,销毁代替品
if (drag_icon)
{
Destroy(drag_icon2);
Destroy(drag_icon);
}
}
public void OnDrop(PointerEventData eventData)
{
//根据代替品的信息,改变当前对象的Sprite。
var obj = eventData.pointerDrag;
this.GetComponent<Image>().sprite = obj.GetComponent<Image>().sprite;
}
}
3.将Canvas上的Canvas组件的RenderMode改为Screen Space-Camera或者World Space,就OK了。
///
注意事项:
1.
脚本需要先引入
using UnityEngine.UI;
using UnityEngine.EventSystems;
2.
引入EventSystems后,继承IDragHandler, IBeginDragHandler, IEndDragHandler, IDropHandler
其分别代表 拖动,开始拖动,结束拖动,拖动目标 ,然后分别实现其相关的处理函数:
public void OnBeginDrag(PointerEventData eventData);
public void OnDrag(PointerEventData eventData);
public void OnEndDrag(PointerEventData eventData) ;
public void OnEndDrag(PointerEventData eventData) ;
3.
在创建代替品后,代码添加CanvasGroup组价,并将blocksRaycasts设为false;
这样可以防止其他物体被代替品遮挡,导致拖动目标位置的GameObject无法事件监测,OnDrop(PointerEventData eventData)函数无法执行。