【UGUI】Unity 背包系统实现02:道具信息提示与显示

在游戏开发中,背包系统是一个常见的功能模块,用于管理玩家拾取的物品。本文将详细介绍如何在 Unity 中实现一个简单的背包系统,包括道具信息的提示和显示功能。我们将通过代码和场景搭建来逐步实现这一功能。

1. 功能需求清单

在实现背包系统时,我们需要满足以下功能需求:

  1. 初始化物品栏:在游戏启动时,初始化背包界面,并添加一些启动物资。

  2. 拾取物体到背包:玩家可以拾取场景中的物体,并将其添加到背包中。

  3. 鼠标滑入显示道具信息:当鼠标滑入背包中的道具时,显示该道具的名称和图标。

  4. 鼠标点击显示道具信息:当鼠标点击背包中的道具时,显示该道具的详细信息。

2. 程序逻辑过程

2.1 初始化物品栏

在游戏启动时,我们需要动态生成背包格子,并为每个格子设置图标和名称。这些格子将作为道具的容器。

2.2 拾取物体到背包

玩家可以通过某种方式(如点击、碰撞等)拾取场景中的物体,并将其添加到背包中。这个功能可以通过扩展代码来实现,本文暂不详细讨论。

2.3 鼠标滑入显示道具信息

当鼠标滑入某个道具格子时,我们需要显示一个提示框,提示框中包含该道具的名称和图标。提示框的位置需要跟随鼠标移动。

2.4 鼠标点击显示道具信息

当鼠标点击某个道具格子时,我们需要显示一个详细信息面板,面板中包含该道具的名称和图标。

3. 必要的场景搭建

在 Unity 中,我们需要搭建一个简单的场景来测试背包系统。场景中需要包含以下元素:

  • Canvas:用于显示 UI 元素。

  • Grid Layout Group:用于排列背包格子。

  • 提示框和信息面板:用于显示道具信息。

  • 道具格子模板:用于动态生成背包格子。

4.代码步骤解释

## 1. 初始化物品栏

### 代码片段

```csharp
private void Awake()
{
    // 通过标签找到提示框和信息面板
    OneTip = GameObject.FindGameObjectWithTag("OneTip");
    InfoRect = GameObject.FindGameObjectWithTag("InfoRect");

    // 初始化系统数据
    for (int i = 0; i < 10; i++)
    {
        GameObject TempCloneGrid = GameObject.Instantiate(GridMuban, GridParentTrans);
        // 修改道具的图标
        TempCloneGrid.transform.GetChild(0).GetChild(0).GetComponent<Image>().sprite = oneIamge[i];
        // 修改道具的名字
        TempCloneGrid.transform.GetChild(1).GetChild(0).GetComponent<TextMeshProUGUI>().text = Name[i];
        // 为每个道具添加侦听功能
        TempCloneGrid.AddComponent<UInterMaager232>();
    }
}
```

### 解释

1. **查找提示框和信息面板**:
   ```csharp
   OneTip = GameObject.FindGameObjectWithTag("OneTip");
   InfoRect = GameObject.FindGameObjectWithTag("InfoRect");
   ```
   通过 `GameObject.FindGameObjectWithTag` 方法查找场景中带有特定标签的对象,分别赋值给 `OneTip` 和 `InfoRect`。

2. **动态生成背包格子**:
   ```csharp
   for (int i = 0; i < 10; i++)
   {
       GameObject TempCloneGrid = GameObject.Instantiate(GridMuban, GridParentTrans);
   ```
   循环生成 10 个背包格子,使用 `GameObject.Instantiate` 方法克隆 `GridMuban` 模板,并将其父物体设置为 `GridParentTrans`。

3. **修改道具的图标**:
   ```csharp
   TempCloneGrid.transform.GetChild(0).GetChild(0).GetComponent<Image>().sprite = oneIamge[i];
   ```
   获取克隆的格子的子物体的子物体的 `Image` 组件,并设置其 `sprite` 属性为 `oneIamge` 数组中的对应图标。

4. **修改道具的名字**:
   ```csharp
   TempCloneGrid.transform.GetChild(1).GetChild(0).GetComponent<TextMeshProUGUI>().text = Name[i];
   ```
   获取克隆的格子的子物体的子物体的 `TextMeshProUGUI` 组件,并设置其 `text` 属性为 `Name` 数组中的对应名称。

5. 添加交互管理脚本**:
 
   TempCloneGrid.AddComponent<UInterMaager232>();
   
   为每个克隆的格子添加 `UInterMaager232` 脚本,以便处理交互事件。

2. 鼠标滑入显示道具信息

代码片段


public void OnPointerEnter(PointerEventData eventData)
{
    Debug.Log("鼠标滑入了");
    MoveTip();
    // 显示提示框并设置内容
    if (!InventoryManager.OneTip.activeSelf)
    {
        InventoryManager.OneTip.SetActive(true);
        InventoryManager.OneTip.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = this.transform.GetChild(1).GetChild(0).GetComponent<TextMeshProUGUI>().text;
        InventoryManager.OneTip.transform.GetChild(1).GetComponent<Image>().sprite = this.transform.GetChild(0).GetChild(0).GetComponent<Image>().sprite;
    }
}
```

解释

1. **显示提示框**:

   if (!InventoryManager.OneTip.activeSelf)
   {
       InventoryManager.OneTip.SetActive(true);
   ```
   检查提示框是否处于激活状态,如果未激活则激活提示框。

2. **设置提示框内容**:
   ```csharp
   InventoryManager.OneTip.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = this.transform.GetChild(1).GetChild(0).GetComponent<TextMeshProUGUI>().text;
   InventoryManager.OneTip.transform.GetChild(1).GetComponent<Image>().sprite = this.transform.GetChild(0).GetChild(0).GetComponent<Image>().sprite;
   ```
   设置提示框中的文本和图标,使其与鼠标滑入的道具格子内容一致。

3. **跟随鼠标移动**:
   ```csharp
   MoveTip();
   ```
   调用 `MoveTip` 方法,使提示框跟随鼠标移动。

## 3. 鼠标点击显示道具信息

### 代码片段

```csharp
public void OnPointerClick(PointerEventData eventData)
{
    // 关闭提示框
    InventoryManager.OneTip.SetActive(false);
    Debug.Log("鼠标点击了");

    // 切换信息面板的显示状态
    if (InventoryManager.InfoRect.activeSelf)
    {
        InventoryManager.InfoRect.SetActive(false);
    }
    else
    {
        InventoryManager.InfoRect.SetActive(true);
        // 设置信息面板的内容
        InventoryManager.InfoRect.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = this.transform.GetChild(1).GetChild(0).GetComponent<TextMeshProUGUI>().text;
        InventoryManager.InfoRect.transform.GetChild(1).GetComponent<Image>().sprite = this.transform.GetChild(0).GetChild(0).GetComponent<Image>().sprite;
    }
}
 

 解释

1. **关闭提示框**:
   ```csharp
   InventoryManager.OneTip.SetActive(false);
   ```
   关闭提示框,避免与信息面板重叠。

2. **切换信息面板的显示状态**:
   ```csharp
   if (InventoryManager.InfoRect.activeSelf)
   {
       InventoryManager.InfoRect.SetActive(false);
   }
   else
   {
       InventoryManager.InfoRect.SetActive(true);
   ```
   检查信息面板是否处于激活状态,如果已激活则隐藏,否则显示信息面板。

3. **设置信息面板内容**:
   ```csharp
   InventoryManager.InfoRect.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = this.transform.GetChild(1).GetChild(0).GetComponent<TextMeshProUGUI>().text;
   InventoryManager.InfoRect.transform.GetChild(1).GetComponent<Image>().sprite = this.transform.GetChild(0).GetChild(0).GetComponent<Image>().sprite;
   ```
   设置信息面板中的文本和图标,使其与鼠标点击的道具格子内容一致。

## 4. 提示框跟随鼠标移动

### 代码片段

```csharp
void MoveTip()
{
    RectTransform TipObject = InventoryManager.OneTip.GetComponent<RectTransform>();

    // 获取鼠标在屏幕上的位置
    Vector3 mousePosition = Input.mousePosition;

    // 将屏幕坐标转换为画布坐标
    Vector2 canvasPosition;
    RectTransformUtility.ScreenPointToLocalPointInRectangle(
        TipObject.parent as RectTransform, // 使用父对象的RectTransform
        mousePosition,
        null, // 如果Canvas是Overlay模式,可以传null
        out canvasPosition);

    // 计算对象在鼠标右下角的位置
    Vector2 offset = new Vector2(TipObject.rect.width / 2, -TipObject.rect.height / 2f); // 右下角偏移

    // 设置对象的位置
    TipObject.localPosition = canvasPosition + offset;
}
```

### 解释

1. **获取鼠标位置**:
   ```csharp
   Vector3 mousePosition = Input.mousePosition;
   ```
   获取鼠标在屏幕上的位置。

2. **转换坐标**:
   ```csharp
   RectTransformUtility.ScreenPointToLocalPointInRectangle(
       TipObject.parent as RectTransform, // 使用父对象的RectTransform
       mousePosition,
       null, // 如果Canvas是Overlay模式,可以传null
       out canvasPosition);
   ```
   将屏幕坐标转换为画布坐标。

3. **计算偏移**:
   ```csharp
   Vector2 offset = new Vector2(TipObject.rect.width / 2, -TipObject.rect.height / 2f); // 右下角偏移
   ```
   计算提示框在鼠标右下角的位置偏移。

4. **设置位置**:
   ```csharp
   TipObject.localPosition = canvasPosition + offset;
   ```
   设置提示框的位置,使其跟随鼠标移动。

## 总结

通过以上步骤和代码解释,我们实现了一个简单的背包系统,包括道具信息的提示和显示功能。通过动态生成背包格子、处理鼠标事件,我们可以在 Unity 中轻松实现这一功能。希望本文对你在 Unity 中开发背包系统有所帮助。

5. 完整代码 + 注释

5.1 InventoryManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;public class InventoryManager : MonoBehaviour
{public GameObject GridMuban; // 背包格子模板public Transform GridParentTrans; // 背包格子的父物体public Sprite[] oneIamge = new Sprite[10]; // 道具图标数组public string[] Name = new string[10]; // 道具名称数组public static GameObject OneTip; // 提示框public static GameObject InfoRect; // 信息面板private void Awake(){// 通过标签找到提示框和信息面板OneTip = GameObject.FindGameObjectWithTag("OneTip");InfoRect = GameObject.FindGameObjectWithTag("InfoRect");// 初始化系统数据for (int i = 0; i < 10; i++){GameObject TempCloneGrid = GameObject.Instantiate(GridMuban, GridParentTrans);// 修改道具的图标TempCloneGrid.transform.GetChild(0).GetChild(0).GetComponent<Image>().sprite = oneIamge[i];// 修改道具的名字TempCloneGrid.transform.GetChild(1).GetChild(0).GetComponent<TextMeshProUGUI>().text = Name[i];// 为每个道具添加侦听功能TempCloneGrid.AddComponent<UInterMaager232>();}}private void Start(){// 初始状态下隐藏提示框和信息面板if (OneTip.activeSelf){OneTip.SetActive(false);}if (InfoRect.activeSelf){InfoRect.SetActive(false);}}
}

5.2 UInterMaager232.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using TMPro;
using UnityEngine.UI;public class UInterMaager232 : MonoBehaviour, IPointerEnterHandler, IPointerClickHandler, IPointerExitHandler
{public void OnPointerClick(PointerEventData eventData){// 关闭提示框InventoryManager.OneTip.SetActive(false);Debug.Log("鼠标点击了");// 切换信息面板的显示状态if (InventoryManager.InfoRect.activeSelf){InventoryManager.InfoRect.SetActive(false);}else{InventoryManager.InfoRect.SetActive(true);// 设置信息面板的内容InventoryManager.InfoRect.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = this.transform.GetChild(1).GetChild(0).GetComponent<TextMeshProUGUI>().text;InventoryManager.InfoRect.transform.GetChild(1).GetComponent<Image>().sprite = this.transform.GetChild(0).GetChild(0).GetComponent<Image>().sprite;}}public void OnPointerEnter(PointerEventData eventData){Debug.Log("鼠标滑入了");MoveTip();// 显示提示框并设置内容if (!InventoryManager.OneTip.activeSelf){InventoryManager.OneTip.SetActive(true);InventoryManager.OneTip.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = this.transform.GetChild(1).GetChild(0).GetComponent<TextMeshProUGUI>().text;InventoryManager.OneTip.transform.GetChild(1).GetComponent<Image>().sprite = this.transform.GetChild(0).GetChild(0).GetComponent<Image>().sprite;}}public void OnPointerExit(PointerEventData eventData){// 关闭提示框if (InventoryManager.OneTip.activeSelf){InventoryManager.OneTip.SetActive(false);}}void MoveTip(){RectTransform TipObject = InventoryManager.OneTip.GetComponent<RectTransform>();// 获取鼠标在屏幕上的位置Vector3 mousePosition = Input.mousePosition;// 将屏幕坐标转换为画布坐标Vector2 canvasPosition;RectTransformUtility.ScreenPointToLocalPointInRectangle(TipObject.parent as RectTransform, // 使用父对象的RectTransformmousePosition,null, // 如果Canvas是Overlay模式,可以传nullout canvasPosition);// 计算对象在鼠标右下角的位置Vector2 offset = new Vector2(TipObject.rect.width / 2, -TipObject.rect.height / 2f); // 右下角偏移// 设置对象的位置TipObject.localPosition = canvasPosition + offset;}
}

6. 脚本挂载和赋值

6.1 场景搭建

  1. Canvas:在场景中创建一个 Canvas,用于显示 UI 元素。

  2. Grid Layout Group:在 Canvas 下创建一个 Panel,并添加 Grid Layout Group 组件,用于排列背包格子。

  3. 提示框和信息面板:在 Canvas 下创建两个 Panel,分别命名为 OneTip 和 InfoRect,并分别添加 TextMeshPro 和 Image 组件。

  4. 道具格子模板:在 Canvas 下创建一个 Panel,命名为 GridMuban,并添加 Image 和 TextMeshPro 组件,用于显示道具的图标和名称。

6.2 脚本挂载

  1. InventoryManager:将 InventoryManager 脚本挂载到 Canvas 上,并将 GridMubanGridParentTransoneIamge 和 Name 字段赋值。

  2. UInterMaager232:该脚本会自动挂载到每个生成的背包格子上,无需手动挂载。

6.3 赋值

  1. GridMuban:将 GridMuban 对象拖拽到 InventoryManager 脚本的 GridMuban 字段。

  2. GridParentTrans:将 GridParentTrans 对象拖拽到 InventoryManager 脚本的 GridParentTrans 字段。

  3. oneIamge:将道具图标拖拽到 InventoryManager 脚本的 oneIamge 数组中。

  4. Name:将道具名称填入 InventoryManager 脚本的 Name 数组中。

总结

通过以上步骤,我们实现了一个简单的背包系统,包括道具信息的提示和显示功能。通过动态生成背包格子、处理鼠标事件,我们可以在 Unity 中轻松实现这一功能。希望本文对你在 Unity 中开发背包系统有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/19269.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

java基础概念31:常见API-Runtime

一、Runtime类常用方法 Runtime&#xff1a;表示当前虚拟机JVM的运行环境&#xff0c;只能有一个。 【注意】&#xff1a; 获取Runtime对象&#xff0c;只能通过getRuntime静态方法。 好处&#xff1a;不管在哪个类中调用Runtime方法&#xff0c;获取的都是同一个对象。即&…

SpringBoot 之整合gRPC

父工程中引入基本的依赖&#xff1a; <modules><module>api</module><module>client</module><module>service</module></modules><parent><artifactId>spring-boot-starter-parent</artifactId><group…

高性能linux服务器运维实战 运维深入实践

用户权限管理 用户与用户组 用户与角色分类 用户是根据角色定义的。可分三类用户角色&#xff0c;root用户&#xff0c;普通用户&#xff0c;虚拟用户 虚拟用户实际不存在&#xff0c;只是为了方便管理&#xff0c;满足进程或文件的属主需求 用户和组配置文件 /etc/passw…

景联文科技:以全面数据处理服务推动AI创新与产业智能化转型

数据标注公司在人工智能领域扮演着重要角色&#xff0c;通过提供高质量的数据标注服务&#xff0c;帮助企业和组织训练和优化机器学习模型。从需求分析到数据交付&#xff0c;每一个步骤都需要严格把控&#xff0c;确保数据的质量和安全性。 景联文科技是一家专业的数据采集与标…

上市公司企业研发操纵数据集(2008-2023年)

一、数据介绍&#xff1a;参考《财会月刊》苑泽明&#xff08;2020&#xff09;老师的做法&#xff0c;具体模型如下所示&#xff0c;TA 为总资产&#xff1b;RD 为研发支出&#xff1b;MV 为企业市值取对数&#xff1b;TBQ 为企业托宾 Q值&#xff1b;INT 为营业利润&#xff…

Maven的下载安装及配置

一、下载Maven 1、访问Maven官网&#xff1a; 打开浏览器&#xff0c;访问Maven的官方网站&#xff1a;Download Apache Maven – Maven 2、选择Maven版本&#xff1a; 在下载页面上&#xff0c;选择适合您操作系统的Maven版本。通常&#xff0c;Maven提供二进制zip归档和tar…

ISCTF 2024 web

ISCTF 2024 web 小蓝鲨的冒险 源码&#xff1a; <?php error_reporting(0); highlight_file(__FILE__); $a "isctf2024"; $b $_GET["b"]; parse_str($b); echo "小蓝鲨开始闯关&#xff0c;你能帮助他拿到flag吗?<br>"; if ($a…

Loopy为何成为IP联名新顶流,如何赋能品牌营销新高度?

在当今竞争激烈的市场环境中&#xff0c;跨界合作已成为品牌营销的重要策略之一。一个成功的跨界合作案例&#xff0c;便是Loopy IP与多个品牌的深度合作。这只来自韩国动画片《小企鹅Pororo》中的配角&#xff0c;凭借一套打工人表情包在中国社交网络迅速走红&#xff0c;并逐…

Mendix 创客访谈录|Mendix 助力西门子原生数字化工厂精益高效

本期创客 向宇轩 西门子数控&#xff08;南京&#xff09;有限公司 数字化工程师 大家好&#xff0c;我是向宇轩。专业背景是计算机科学与技术&#xff0c;毕业后加入西门子数控&#xff08;南京&#xff09;有限公司&#xff08;SNC&#xff09;担任数字化工程师的职务&#x…

C++ —— string类(上)

目录 string的介绍 string类功能的使用介绍 constructor —— 构造 介绍使用&#xff08;1&#xff09;&#xff08;2&#xff09;&#xff08;4&#xff09; &#xff1a;构造、拷贝构造、带参构造 介绍&#xff08;3&#xff09;&#xff1a;拷贝string类对象的一部分字符…

关于Qt C++中connect的几种写法

目录 1. 传统的槽函数写法 2. 使用函数指针的connect写法&#xff08;5.0&#xff09; 3. Lambda表达式作为槽函数&#xff08;C11&#xff09; 4.使用QOverload选择重载信号的写法 这connect函数就像是编程世界里的“茴”字&#xff0c;千变万化&#xff0c;各有千秋。咱们…

(二)PyTorch简要教学

文章目录 PyTorch教学一、训练一个神经网络二、用PyTorch是怎么去做的&#xff08;一&#xff09;Dataset & DataLoader&#xff08;二&#xff09;Tensors&#xff08;1&#xff09;Tensor是什么&#xff08;2&#xff09;怎么获得Tensor&#xff08;3&#xff09;Tensor相…

GRPC实现

1.首先下载对应编译插件&#xff0c;这里不再提供下载 2.编写proto文件 3.编写完成用命令生成go文件 protoc --go_out. --go-grpc_out. *.proto --go_out. 其中的. 是说你要编译的 .proto 文件目录为当前目录&#xff0c;按需修改 --go-grpc_out.&#xff0c;其中的. 是说你生…

Path does not exist: file:/D:/pythonProject/spark/main/datas/input/u.data

出现标题中的错误原因可能是&#xff1a; 1.文件路径书写错误&#xff1b; 2.文件本身不存在。 从图中可以看出&#xff0c;数据源文件是存在的&#xff0c;但是读取不到文件&#xff0c;说明代码中的文件路径写错了&#xff0c;从报错的结果可以看出&#xff0c;python在D:/…

Wallpaper壁纸制作学习记录01

导入图像 打开wallpaper软件&#xff0c;找到下方的播放列表&#xff0c;选择壁纸编辑器。 弹出下列界面&#xff0c;在创建壁纸处可以选择图片拖入。 在开始导入任何图像之前&#xff0c;请首先确保主背景图像表示实际屏幕分辨率。展示示例图像是 1920 x 1080&#xff0c;这…

【知识科普】统一身份认证CAS

什么是CAS 综合概述一、CAS概述二、CAS的组成与工作原理三、CAS的特性与支持四、CAS的应用场景 示例展示场景设定CAS认证过程 其他认证细节CAS认证过程的细节CAS认证过程的特性 参考文献 综合概述 统一身份认证CAS&#xff08;Central Authentication Service&#xff09;&…

计算机网络-MSTP工作原理

前面大致学习了MSTP基础概念与组成&#xff0c;今天来了解MSTP的工作原理。 一、MSTP拓扑计算&#xff1a; MSTP可以将整个二层网络划分为多个MST域&#xff0c;各个域之间通过计算生成CST&#xff0c;域内生成IST&#xff0c;CST和IST构成了整个交换设备网络的CIST。 域内还可…

面试题:Kafka(一)

1. Kafka如何保证消息不丢失 生产者发送消息到Brocker丢失 设置异步发送 消息重试 消息在Brocker中存储丢失 发送确认机制acks 消费者从Brocker接收消息丢失 Kafka 中的分区机制指的是将每个主题划分成多个分区&#xff08;Partition&#xff09;topic分区中消息只能由消费者…

odoo 创建应用

1、通过手脚架命令创建文件结构&#xff08;完全可以手动一个个文件/文件夹建&#xff09; odoo-bin scaffold <模块名> <模块放置路径> 在odoo根目录路径执行命令行&#xff1a;./odoo-bin scaffold my_library exte_addons 执行结果&#xff1a; 参考文章&…

十四、SpringMVC的执行流程

文章目录 1. SpringMVC常用组件2. DispatcherServlet初始化过程3. DispatcherServlet调用组件处理请求4. SpringMVC的执行流程 1. SpringMVC常用组件 2. DispatcherServlet初始化过程 3. DispatcherServlet调用组件处理请求 4. SpringMVC的执行流程