当前位置: 首页 > article >正文

Unity3D仿星露谷物语开发18之添加道具到库存栏

1、目标

当角色拾取道具时能够显示在库存栏中,同时可以显示拾取道具的数量。

2、TextMeshPro组件

TextMeshPro(TMP)是一个Unity文本组件,TMP为文本样式和纹理提供了强大的灵活性。

TMP与Text的差异:

  • TMP文本样式比Text文本样式更加丰富和灵活
  • TMP对应的Shader支持描边、阴影和颜色渐变等美术效果,而且不会额外增加网格的顶点数量。而Text需要添加Shadow组件、Outline组件等才能支持这些美术效果,且会增加网格的顶点数量。
  • 性能方面,TMP比Text会占用更多的堆内存,消耗更多的渲染开销。
  • TMP是以哦那个SDF技术来渲染字体,而Text使用FreeType库来渲染字体。
  • TMP引用字体有限,如果没找到字体最终是CallBack不到系统字体,会显示一个方框。而Text能CallBack回系统字体。

3、创建插槽预制体

(1)创建UIInventorySlot

点击UIInventoryBar,然后按F键,Scene界面聚焦在UIInventoryBar物体上。

我们需要在里面创建一系列的库存槽,在插槽中操纵图像和文本类型的项目数。

在UIInventoryBar下创建空物体命名为UIInventorySlot。

重置它的位置为Middle Left。

然后给UIInventorySlot添加Image组件,设置属性如下:

Preserve Aspect:当勾选这个选项之后再对图片进行操作时,会保持图片的宽度和高度的比例不发生改变。

然后再添加Canvas Group组件。

(2)创建InventoryHighlight

在UIInventorySlot下创建InventoryHighlight对象,增加这个作用是:后续点击slot时,会有个红色方框突出一下,表明选中了当前slot。

增加Image组件,并设置属性如下:

目前不需要突出显示某个slot,所以需要设置color.alpha=0。

(3)创建TMP文本

在UIInventorySlot下Create -> UI -> Text - TextMeshPro。

接下来创建字体资源,Window -> TextMeshPro -> Font Asset Creator。

在Source Font File中选择Peepo,点击“Generate Font Atlas”,点击"Save"保存到默认文件夹下。

然后点击Text(TMP)对象,设置属性如下:

(4)创建预制体

在Assets -> Prefabs下创建UI目录,并将UIInventorySlot拖入其中。

(5)创建多个Slot

复制多个UIInventorySlot到UIInventoryBar中,通过调整Pos X值使得每个UIInventorySlot可以对号入座。

4、创建UIInventorySlot脚本

在Assets -> Scripts -> UI -> UIInventory下创建UIInventorySlot脚本。

using UnityEngine;
using TMPro;
using UnityEngine.UI;

public class UIInventorySlot : MonoBehaviour
{
    public Image inventorySlotHighlight;
    public Image inventorySlotImage;
    public TextMeshProUGUI textMeshProUGUI;

    [HideInInspector] public ItemDetails itemDetails;
    [HideInInspector] public int itemQuantity;

}

双击UIInventorySlot预制体,添加UIInventorySlot组件,并设置对应的属性信息如下:

5、优化UIInventoryBar脚本

新增两个变量,一个是默认查抄的图案为空图案,另一个是插槽集合需要配置进来。

一般在OnEnable()和OnDisable()方法中监听事件。

新增部分代码如下:

[SerializeField] private Sprite blank16x16sprite = null; // 插槽默认图案
[SerializeField] private UIInventorySlot[] inventorySlot = null; // 所有插槽集合

private void OnDisable()
{
    EventHandler.InventoryUpdatedEvent -= InventoryUpdated;
}

private void InventoryUpdated(InventoryLocation inventoryLocation, List<InventoryItem> inventoryList)
{
    if (inventoryLocation == InventoryLocation.player)
    {
        ClearInventorySlots();

        if (inventorySlot.Length > 0 && inventoryList.Count > 0)
        {
            for (int i = 0; i < inventorySlot.Length; i++)
            {
                if (i < inventoryList.Count)
                {
                    int itemCode = inventoryList[i].itemCode;

                    ItemDetails itemDetails = InventoryManager.Instance.GetItemDetails(itemCode);

                    if (itemDetails != null)
                    {
                        // add images and details to inventory item slot
                        inventorySlot[i].inventorySlotImage.sprite = itemDetails.itemSprite;
                        inventorySlot[i].textMeshProUGUI.text = inventoryList[i].itemQuantity.ToString();
                        inventorySlot[i].itemDetails = itemDetails;
                        inventorySlot[i].itemQuantity = inventoryList[i].itemQuantity;
                    }
                }
                else
                {
                    break;
                }

            }
        }
    }
}

private void ClearInventorySlots()
{
    if(inventorySlot.Length > 0)
    {
        // loop through inventory slots and update with blank sprite
        for(int i = 0; i < inventorySlot.Length; i++)
        {
            inventorySlot[i].inventorySlotImage.sprite = blank16x16sprite;
            inventorySlot[i].textMeshProUGUI.text = "";
            inventorySlot[i].itemDetails = null;
            inventorySlot[i].itemQuantity = 0;
        }
    }
}

private void OnEnable()
{
    EventHandler.InventoryUpdatedEvent += InventoryUpdated;
}

完整代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIInventoryBar : MonoBehaviour
{
    [SerializeField] private Sprite blank16x16sprite = null; // 插槽默认图案
    [SerializeField] private UIInventorySlot[] inventorySlot = null; // 所有插槽集合

    private RectTransform rectTransform;

    private bool _isInventoryBarPositionBottom = true;

    public bool IsInventoryBarPositionBottom { get { return _isInventoryBarPositionBottom;} set { _isInventoryBarPositionBottom = value; } }

    private void Awake()
    {
        rectTransform = GetComponent<RectTransform>();
    }

    private void OnDisable()
    {
        EventHandler.InventoryUpdatedEvent -= InventoryUpdated;
    }

    private void InventoryUpdated(InventoryLocation inventoryLocation, List<InventoryItem> inventoryList)
    {
        if (inventoryLocation == InventoryLocation.player)
        {
            ClearInventorySlots();

            if (inventorySlot.Length > 0 && inventoryList.Count > 0)
            {
                for (int i = 0; i < inventorySlot.Length; i++)
                {
                    if (i < inventoryList.Count)
                    {
                        int itemCode = inventoryList[i].itemCode;

                        ItemDetails itemDetails = InventoryManager.Instance.GetItemDetails(itemCode);

                        if (itemDetails != null)
                        {
                            // add images and details to inventory item slot
                            inventorySlot[i].inventorySlotImage.sprite = itemDetails.itemSprite;
                            inventorySlot[i].textMeshProUGUI.text = inventoryList[i].itemQuantity.ToString();
                            inventorySlot[i].itemDetails = itemDetails;
                            inventorySlot[i].itemQuantity = inventoryList[i].itemQuantity;
                        }
                    }
                    else
                    {
                        break;
                    }

                }
            }
        }
    }

    private void ClearInventorySlots()
    {
        if(inventorySlot.Length > 0)
        {
            // loop through inventory slots and update with blank sprite
            for(int i = 0; i < inventorySlot.Length; i++)
            {
                inventorySlot[i].inventorySlotImage.sprite = blank16x16sprite;
                inventorySlot[i].textMeshProUGUI.text = "";
                inventorySlot[i].itemDetails = null;
                inventorySlot[i].itemQuantity = 0;
            }
        }
    }

    private void OnEnable()
    {
        EventHandler.InventoryUpdatedEvent += InventoryUpdated;
    }

    private void Update()
    {
        // Switch inventory bar position depending on player position
        SwitchInventoryBarPosition();
    }

    private void SwitchInventoryBarPosition()
    {
        Vector3 playerViewportPosition = Player.Instance.GetPlayerViewportPosition();

        if (playerViewportPosition.y > 0.3f && IsInventoryBarPositionBottom == false)
        {
            rectTransform.pivot = new Vector2(0.5f, 0f);
            rectTransform.anchorMin = new Vector2(0.5f, 0f);
            rectTransform.anchorMax = new Vector2(0.5f, 0f);
            rectTransform.anchoredPosition = new Vector2(0f, 2.5f);

            IsInventoryBarPositionBottom = true;
        }
        else if (playerViewportPosition.y <= 0.3f && IsInventoryBarPositionBottom == true) 
        {
            rectTransform.pivot = new Vector2(0.5f, 1f);
            rectTransform.anchorMin = new Vector2(0.5f, 1f);
            rectTransform.anchorMax = new Vector2(0.5f, 1f);
            rectTransform.anchoredPosition = new Vector2(0f, -2.5f);

            IsInventoryBarPositionBottom = false;
        }
    }
}

点击UIInventoryBar对象,

1)配置Blank 16x16sprite对象如下。

2)点击右上角的锁按钮,然后把12个slot拖到Inventory Slot变量中。

6、优化InventoryManager脚本

注释所有调用DebugPrintInventoryList的地方(共2个)。

执行程序,效果如下:


http://www.kler.cn/a/470353.html

相关文章:

  • SQL使用视图
  • EyeSoothe: Your Ultimate Eye Health Companion
  • Linux性能优化-系列文章-汇总
  • STM32 软件I2C读写
  • 【2025最新计算机毕业设计】基于SpringBoot+Vue智慧养老医护系统(高质量源码,提供文档,免费部署到本地)【提供源码+答辩PPT+文档+项目部署】
  • clickhouse query_log 常用查询语句
  • 按键精灵ios脚本教程:用函数来实现将图片保存到相册
  • Elasticsearch VS Easysearch 性能测试
  • Golang学习笔记_18——接口
  • 海外云服务器能用来做什么?
  • python 如何调整word 文档页眉页脚
  • 移动电商的崛起与革新:以开源AI智能名片2+1链动模式S2B2C商城小程序为例的深度剖析
  • 培训机构Day23
  • 在 Vue 中使用 @ngageoint/geopackage 实现 GeoPackage 数据处理与可视化
  • 常见转义字符
  • 人工智能安全——联邦学习的安全攻击与防护
  • Map集合
  • QT6编程入门(一)
  • 每日一题:BM2 链表内指定区间反转
  • 分布式搜索引擎之elasticsearch基本使用3
  • 电脑如何无线控制手机?
  • VVenC 编码器源码结构与接口函数介绍
  • 复古柯达胶片电影效果肖像风景街头摄影Lightroom调色预设 Koda Film Preset Pack | Cinematic Presets
  • Django 模型
  • 20250106面试
  • R语言的计算机基础