Unity 背包物品拖动/物品互换
简单记录,方便使用
创建好背包格子
格子的tag值需要设置成Grid 物品tag值需要设置成 Good (自己设置成什么都行) 设置其他参数 需要在脚本中修改
下面上代码 一个继承 MonoBehaviour 一个继承 Button
第一种
using System; using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; using UnityEngine.UI; /// <summary> /// 本脚本挂在物品上运行即可 /// </summary> public class DragImage : MonoBehaviour { private Transform beginParentTransform; //记录开始拖动时的父级对象 private Transform canvasParent; private EventTrigger trigger; // Use this for initialization void Start() { canvasParent = GameObject.Find("Canvas").transform; if (!GetComponent<EventTrigger>()) { trigger = gameObject.AddComponent<EventTrigger>(); } else { trigger = gameObject.GetComponent<EventTrigger>(); } //开始拖拽的事件 UnityAction<BaseEventData> click = new UnityAction<BaseEventData>(Begin); EventTrigger.Entry myclick = new EventTrigger.Entry(); myclick.eventID = EventTriggerType.BeginDrag; myclick.callback.AddListener(click); trigger.triggers.Add(myclick); //拖拽中的事件 UnityAction<BaseEventData> _click = new UnityAction<BaseEventData>(OnDrag); EventTrigger.Entry myclick_ = new EventTrigger.Entry(); myclick_.eventID = EventTriggerType.Drag; myclick_.callback.AddListener(_click); trigger.triggers.Add(myclick_); //结束拖拽的事件 UnityAction<BaseEventData> Endclick = new UnityAction<BaseEventData>(End); EventTrigger.Entry Endclick_ = new EventTrigger.Entry(); Endclick_.eventID = EventTriggerType.EndDrag; Endclick_.callback.AddListener(Endclick); trigger.triggers.Add(Endclick_); } /// <summary> /// 开始拖动时 /// </summary> public void Begin(BaseEventData data) { if (transform.parent == canvasParent) return; beginParentTransform = transform.parent; transform.SetParent(canvasParent); } /// <summary> /// 拖动中 /// </summary> /// <param name="e">UI事件数据</param> public void OnDrag(BaseEventData e) { transform.position = Input.mousePosition; if (transform.GetComponent<Image>().raycastTarget) transform.GetComponent<Image>().raycastTarget = false; } /// <summary> /// 结束时 /// </summary> public void End(BaseEventData data) { PointerEventData e = data as PointerEventData; if (e == null) return; GameObject target = e.pointerCurrentRaycast.gameObject; if (target.tag == "Grid") //如果当前拖动物体下是:格子(没有物品)时 { SetPos_Parent(transform, target.transform); transform.GetComponent<Image>().raycastTarget = true; } else if (target.tag == "Good") //如果是物品 { SetPos_Parent(transform, target.transform.parent); //将当前拖动物品设置到目标位置 target.transform.SetParent(canvasParent); //目标物品设置到 UI 顶层 SetPos_Parent(target.transform, beginParentTransform); //再将目标物品设置到开始拖动物品的父物体 来完成物品的切换 transform.GetComponent<Image>().raycastTarget = true; } else //其他任何情况,物体回归原始位置 { SetPos_Parent(transform, beginParentTransform); transform.GetComponent<Image>().raycastTarget = true; } } /// <summary> /// 设置父物体,UI位置归正 /// </summary> /// <param name="targetods">对象Transform</param> /// <param name="parent">要设置到的父级</param> private void SetPos_Parent(Transform targetods, Transform parent) { targetods.SetParent(parent); targetods.position = parent.position; } }
第一种实现来回拖拽的效果,可以相互替换
扩展(实现在背包里拖拽到其他固定地方,在从其他地方拖到背包)

using System; using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; using UnityEngine.UI; /// <summary> /// 本脚本挂在物品上运行即可 /// </summary> public class DragImage : MonoBehaviour { public Transform targerTransform; //目标位置 private Transform beginParentTransform; //记录开始拖动时的父级对象 private Transform canvasParent; private EventTrigger trigger; // Use this for initialization void Start() { canvasParent = GameObject.Find("Canvas").transform; if (!GetComponent<EventTrigger>()) { trigger = gameObject.AddComponent<EventTrigger>(); } else { trigger = gameObject.GetComponent<EventTrigger>(); } //开始拖拽的事件 UnityAction<BaseEventData> click = new UnityAction<BaseEventData>(Begin); EventTrigger.Entry myclick = new EventTrigger.Entry(); myclick.eventID = EventTriggerType.BeginDrag; myclick.callback.AddListener(click); trigger.triggers.Add(myclick); //拖拽中的事件 UnityAction<BaseEventData> _click = new UnityAction<BaseEventData>(OnDrag); EventTrigger.Entry myclick_ = new EventTrigger.Entry(); myclick_.eventID = EventTriggerType.Drag; myclick_.callback.AddListener(_click); trigger.triggers.Add(myclick_); //结束拖拽的事件 UnityAction<BaseEventData> Endclick = new UnityAction<BaseEventData>(End); EventTrigger.Entry Endclick_ = new EventTrigger.Entry(); Endclick_.eventID = EventTriggerType.EndDrag; Endclick_.callback.AddListener(Endclick); trigger.triggers.Add(Endclick_); } /// <summary> /// 开始拖动时 /// </summary> public void Begin(BaseEventData data) { //if (transform.parent == canvasParent) return; beginParentTransform = transform.parent; transform.SetParent(canvasParent); } /// <summary> /// 拖动中 /// </summary> /// <param name="e">UI事件数据</param> public void OnDrag(BaseEventData e) { transform.position = Input.mousePosition; if (transform.GetComponent<Image>().raycastTarget) transform.GetComponent<Image>().raycastTarget = false; // Debug.Log(e); } /// <summary> /// 结束时 /// </summary> public void End(BaseEventData data) { PointerEventData e = data as PointerEventData; if (e == null) return; GameObject target = e.pointerCurrentRaycast.gameObject; if (transform.parent == canvasParent) { SetPos_Parent(transform, beginParentTransform); transform.GetComponent<Image>().raycastTarget = true; } if (target.tag == "Grid"&& target.name == this.name|| target.tag == "Grid" && target.name =="Grid") //如果当前拖动物体下是:格子(没有物品)时 { SetPos_Parent(transform, target.transform); transform.GetComponent<Image>().raycastTarget = true; } else if (target.tag == "Good") //如果是物品 { SetPos_Parent(transform, target.transform.parent); //将当前拖动物品设置到目标位置 target.transform.SetParent(canvasParent); //目标物品设置到 UI 顶层 SetPos_Parent(target.transform, beginParentTransform); //再将目标物品设置到开始拖动物品的父物体 来完成物品的切换 transform.GetComponent<Image>().raycastTarget = true; } else //其他任何情况,物体回归原始位置 { SetPos_Parent(transform, beginParentTransform); transform.GetComponent<Image>().raycastTarget = true; } } /// <summary> /// 设置父物体,UI位置归正 /// </summary> /// <param name="targetods">对象Transform</param> /// <param name="parent">要设置到的父级</param> private void SetPos_Parent(Transform targetods, Transform parent) { targetods.SetParent(parent); targetods.position = parent.position; } }
第二种
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; using System; namespace DragAmer.UI { //继承button 挂在物品上即可 需要其他功能请自行添加 public class CongDragSwapImage : Button, IDragHandler, IBeginDragHandler, IEndDragHandler { private Transform beginParentTransform; //记录开始拖动时的父级对象 private Transform canvasParent; protected override void Start() { base.Start(); canvasParent = GameObject.Find("Canvas").transform; } public void OnBeginDrag(PointerEventData _) { if (transform.parent == canvasParent) return; beginParentTransform = transform.parent; transform.SetParent(canvasParent); } public void OnDrag(PointerEventData _) { transform.position = Input.mousePosition; if (transform.GetComponent<Image>().raycastTarget) transform.GetComponent<Image>().raycastTarget = false; } public void OnEndDrag(PointerEventData e) { GameObject target = e.pointerCurrentRaycast.gameObject; if (target.tag == "Grid") //如果当前拖动物体下是:格子(没有物品)时 { SetPos_Parent(transform, target.transform); transform.GetComponent<Image>().raycastTarget = true; } else if (target.tag == "Good") //如果目标是物品 { SetPos_Parent(transform, target.transform.parent); //将当前拖动物品设置到目标位置 target.transform.SetParent(canvasParent); //目标物品设置到 UI 顶层 SetPos_Parent(target.transform, beginParentTransform); //再将目标物品设置到开始拖动物品的父物体 来完成物品的切换 transform.GetComponent<Image>().raycastTarget = true; } else //其他任何情况,物体回归原始位置 { SetPos_Parent(transform, beginParentTransform); transform.GetComponent<Image>().raycastTarget = true; } } /// <summary> /// 设置父物体,UI位置归正 /// </summary> /// <param name="targetods">对象Transform</param> /// <param name="parent">要设置到的父级</param> private void SetPos_Parent(Transform targetods, Transform parent) { targetods.SetParent(parent); targetods.position = parent.position; } } }
end
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器