麦田物语学习笔记:创建DragItem实现物品的拖拽跟随显示

基本流程

1.代码思路

(1)在SlotUI中使用拖拽接口IBeginDragHandler,IDragHandler,IEndDragHandler

(2)开始拖拽的时候,在屏幕上生成物体,拖拽期间物体显示为当前被拖拽的物体的图标,停止拖拽时图标消失

(3)基于以上,所以我们要获得这个图标的控制,则要去InventoryUI里获得

(4)在停止拖拽的时候检测该位置所对应的GameObject,值得注意的是,这个检测只检测UI元素;之后在代码实现后只能检测到所处格子的TMP,控制台会如下打印.

Amount (UnityEngine.GameObject)

这时就是没有检测到Slot_Bag的对象,原因是因为预制体Slot_Bag的三个子对象都没有解除对鼠标射线检测的限制(Raycast Target),取消后就能正常检测了,输出如下

Slot_Bag (3) (UnityEngine.GameObject)

2.代码实现

在InventoryUI中添加变量

cs 复制代码
[Header("拖拽图片")]
public Image dragItem;

在SlotUI中添加拖拽相关接口

cs 复制代码
public class SlotUI : MonoBehaviour, IPointerClickHandler, IBeginDragHandler, IDragHandler, IEndDragHandler

实现接口

cs 复制代码
public void OnBeginDrag(PointerEventData eventData)
{
    //先判断这个格子能不能被拖拽
    if (itemAmount == 0) return;

    inventoryUI.dragItem.enabled = true;
    inventoryUI.dragItem.sprite = slotImage.sprite;
    //防止图片分辨率不一,导致畸变
    inventoryUI.dragItem.SetNativeSize();
    //提示拖拽的是哪一个
    isSelected = true;
    inventoryUI.UpdateSlotHightlight(slotIndex);

}

public void OnDrag(PointerEventData eventData)
{
    inventoryUI.dragItem.transform.position = Input.mousePosition;
}

public void OnEndDrag(PointerEventData eventData)
{
    inventoryUI.dragItem.enabled = false;

    Debug.Log(eventData.pointerCurrentRaycast.gameObject);
}

最终效果

实现拖拽;松开后消失;被选中物品高亮,相关控制台输出看上面的思路

补充知识点

1.IBeginDragHandler,IDragHandler,IEndDragHandler这三个接口

IBeginDragHandler 接口

  • 概述
    • IBeginDragHandler是在 Unity 的新输入系统(Input System)中用于处理拖动操作开始阶段的接口。当用户开始拖动一个对象(例如,通过鼠标按下并开始移动,或者在触摸屏幕后开始移动手指)时,实现了这个接口的脚本中的相关方法会被调用。
  • 方法和作用
    • 它主要包含OnBeginDrag方法。这个方法接收一个DragEventArgs类型的参数。例如,在一个简单的 Unity 场景中,如果你有一个可拖动的 UI 元素,当用户开始拖动这个元素时,OnBeginDrag方法可以用来记录拖动开始的位置、获取被拖动对象的初始状态等操作。
  • 应用场景
    • 适用于需要在拖动开始时进行初始化操作的情况。比如在一个纸牌游戏中,当玩家开始拖动一张纸牌,你可以在OnBeginDrag方法中记录纸牌的原始位置,设置一些标记来表示这张纸牌正在被拖动,防止其他操作(如自动整理纸牌)的干扰等。

IDragHandler 接口

  • 概述
    • IDragHandler接口用于处理拖动操作的持续过程。在用户开始拖动(IBeginDragHandlerOnBeginDrag方法被调用后)并且手指或者鼠标还在移动的过程中,这个接口中的方法会不断被调用。
  • 方法和作用
    • 它包含OnDrag方法,同样接收PointerEventData类型的参数。在这个方法中,可以根据拖动过程中的位置变化来更新被拖动对象的位置。
  • 应用场景
    • 广泛应用于各种拖动交互场景。比如在一个绘图应用中,当用户拖动画笔工具时,通过OnDrag方法可以在屏幕上绘制线条,线条的路径根据OnDrag方法中获取的拖动位置来确定;在一个文件管理应用中,拖动文件图标在文件夹之间移动时,OnDrag方法可以用来更新文件图标的位置显示,直到拖动操作结束。

IEndDragHandler 接口

  • 概述
    • IEndDragHandler接口用于处理拖动操作的结束阶段。当用户松开鼠标按钮或者抬起手指,结束拖动操作时,这个接口中的方法会被调用。
  • 方法和作用
    • 主要的方法是OnEndDrag,参数也是PointerEventData类型。在这个方法中,可以进行拖动结束后的清理工作,比如将被拖动对象放置到合适的位置、检查是否放置到了有效的目标区域等
  • 应用场景
    • 例如在一个拼图游戏中,当玩家拖动拼图块到正确的位置并松开时,OnEndDrag方法可以检查拼图块是否放置正确,如果正确则将拼图块固定在该位置,否则将其返回原来的位置;在一个拖放文件到回收站的场景中,OnEndDrag方法可以判断文件图标是否被拖放到回收站图标区域内,如果是则执行删除文件的操作,否则不做任何操作。

2.Image组件

详情看这篇文章

这里主要用到其中的Raycast Target,在勾选的情况下会阻止鼠标的射线判断,所以要去掉勾选

3.关于 eventData.pointerCurrentRaycast.gameObject 的一些说明

(1)工作原理
  • pointerCurrentRaycast :这是 Unity 的 PointerEventData 提供的一个属性,用于获取当前指针(如鼠标或触摸)射线检测到的结果。
  • 射线检测的范围
    • 该射线检测是基于 UI 系统 的,因此它只会检测当前场景中 UI 元素 (如 Canvas 下的 ButtonImage 等)。
    • 如果指针指向的是非 UI 的游戏对象(如 3D 场景中的物体),则 pointerCurrentRaycast 不会检测到这些对象。
(2) 检测是否仅限于当前场景的 GameObject
  • 仅限于当前场景的 UI 元素

    • 该检测只会对当前场景中 UI 系统 下的 GameObject 生效。
    • 如果当前场景中有多个 Canvas,且这些 Canvas 都启用了射线检测(Raycast Target),则这些 Canvas 下的 UI 元素都会被检测到。
    • 如果指针指向的是非 UI 的游戏对象(如 3D 模型),则不会被检测到。
  • 跨场景检测

    • 如果当前场景中有多个场景叠加(例如通过 DontDestroyOnLoad 保留的场景),且这些场景中有 UI 元素,则这些 UI 元素也会被检测到。
    • 但如果指针指向的是其他场景中的非 UI 对象,则不会被检测到。

4.Raycast Target详解

  1. 定义
    • 在 Unity 中,Raycast Target是一个与 UI(用户界面)元素相关的重要属性。它主要用于图形射线投射。简单来说,当你有一个射线(例如鼠标点击产生的射线或者通过代码发射的射线)时,Unity 会检查哪些对象具有Raycast Target属性被启用,以确定射线是否 "击中" 了这些对象。
  2. 工作原理
    • 当你在屏幕上进行交互操作(如点击鼠标)时,Unity 会从摄像机向屏幕上的点击位置发射一条射线。这条射线会遍历场景中的所有具有Raycast Target属性的对象。如果射线与一个带有Raycast Target属性且该属性被启用的 UI 元素相交,那么这个 UI 元素就会接收到相关的事件消息,例如OnPointerClickOnPointerDown等。
    • 以一个简单的游戏界面为例,假设有一个按钮和一个文本框。如果按钮的Raycast Target属性被启用,而文本框的被禁用。当你点击按钮所在的位置时,按钮会响应点击事件,因为射线可以 "击中" 它;而点击文本框所在位置时,由于其Raycast Target被禁用,它不会响应点击事件。
  3. 应用场景
    • 按钮交互 :对于 UI 按钮,Raycast Target属性通常是启用的。这样,当玩家点击按钮时,按钮能够接收点击事件并执行相应的操作,如打开一个菜单、触发一段动画或者执行一个游戏逻辑功能。
    • 选择 UI 元素 :在制作游戏菜单或者库存系统时,通过射线投射来确定玩家选择了哪个 UI 元素。例如,在一个装备选择界面中,每个装备图标都有Raycast Target属性,玩家可以通过鼠标点击(射线投射)来选择装备。
  4. 性能考虑
    • 过多地启用Raycast Target属性可能会影响性能。因为每一次射线投射都需要检查所有启用了该属性的对象。在一个复杂的 UI 场景中,如果有大量不必要的 UI 元素都开启了Raycast Target,会增加射线投射的计算量。所以,在实际开发中,对于那些不需要响应射线投射事件的 UI 元素,应该将Raycast Target属性关闭,以提高性能。例如,对于只是用于显示信息的静态文本标签,通常可以禁用Raycast Target,因为它们不需要响应点击等交互事件。
相关推荐
学习和思考16 分钟前
为什么我的vscode有的时候可以跳转,有的时候不能跳转
arm开发·ide·驱动开发·vscode·学习·1024程序员节
兔兔爱学习兔兔爱学习18 分钟前
LangChain4j学习6:agent
人工智能·学习·语言模型
lkbhua莱克瓦2437 分钟前
Java基础——常用API2
java·笔记·github·学习方法
丰锋ff1 小时前
英一2016年真题学习笔记
笔记·学习
摇滚侠1 小时前
Spring Boot3零基础教程,Lambda 表达式与函数式接口,笔记95
java·spring boot·笔记
新子y1 小时前
【小白笔记】稀疏数组 (Sparse Array) 在计算机科学中的存储优化问题
笔记
Lynnxiaowen1 小时前
今天我们学习Linux架构keepalived实现LVS代理双击热备
linux·学习·架构·云计算
摇滚侠1 小时前
Spring Boot3零基础教程,Lambda 表达式的使用,笔记96
spring boot·笔记
charlie1145141912 小时前
HTML 理论系统笔记2
前端·笔记·学习·html·基础·1024程序员节·原生
井队Tell3 小时前
打造高清3D虚拟世界|零基础学习Unity HDRP高清渲染管线(第十天)
学习·3d·unity