麦田物语学习笔记:创建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,因为它们不需要响应点击等交互事件。
相关推荐
朝九晚五ฺ39 分钟前
【Linux探索学习】第二十五弹——动静态库:Linux 中静态库与动态库的详细解析
linux·运维·学习
geniuscrh1 小时前
selenium学习笔记
笔记·学习·selenium
CJenny2 小时前
LangChain 学习笔记
笔记·学习·langchain
博雅智信3 小时前
人工智能计算机视觉学习路线——从基础到深度探索
人工智能·python·学习·计算机视觉·计算机视觉学习路线·申博
go_bai3 小时前
数据结构——栈的实现
c语言·开发语言·数据结构·经验分享·笔记·学习方法
橘子味的茶二3 小时前
opencv 学习(3)
人工智能·opencv·学习
一棵开花的树,枝芽无限靠近你3 小时前
【PPTist】公式编辑、插入音视频、添加动画
前端·笔记·学习·编辑器·ppt·pptist
bloxed3 小时前
Vite源码学习分享(一)
学习
cd小白4 小时前
Linux第二课:LinuxC高级 学习记录day01
linux·c语言·开发语言·学习