【制作100个unity游戏之25】3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱7(附带项目源码)

简介: 【制作100个unity游戏之25】3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱7(附带项目源码)

前言

欢迎来到【制作100个Unity游戏】系列!本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第25篇中,我们将探索如何用unity制作一个3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱等功能,我会附带项目源码,以便你更好理解它。

新增简单的泛型单例

我们会有有很多单例,如果每个单例都去写会很麻烦,所以我们定义泛型单例模式 Singleton,我们将所有的单例都继承这个泛型单例,就省略很多重复的工作

//简单的泛型单例
public class Singleton<T> : MonoBehaviour where T : Singleton<T>
{
    private static T instance;

    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                instance = FindObjectOfType<T>();
                if (instance == null)
                {
                    GameObject obj = new GameObject(typeof(T).Name);
                    instance = obj.AddComponent<T>();
                }
            }
            return instance;
        }
    }

    public void Awake() {
        if(instance == null){
            instance = this as T;
            //确保单例对象在场景切换时不会被销毁
            DontDestroyOnLoad(gameObject);
        }else{
            Destroy(gameObject);
        }
    }
}

调用例子:

public class MySingletonClass : Singleton<MySingletonClass>
{
    // 添加自己的方法和属性
}

消耗品

新增玩家健康类控制脚本

public class PlayerHealth : MonoBehaviour
{
    [SerializeField] private int health = 0; // 玩家健康值
    [SerializeField] private int food = 0;   // 玩家食物值
    [SerializeField] private int water = 0;  // 玩家水分值

    // 增加健康值
    public void AddHealth(int addedHealth)
    {
        health += addedHealth;
    }

    // 增加食物值
    public void AddFood(int addedFood)
    {
        food += addedFood;
    }

    // 增加水分值
    public void AddWater(int addedWater)
    {
        water += addedWater;
    }
}

因为物品都会配置为预制体,如果我们直接在物品上挂载配置触发的事件,变为预制体后事件配置数据会丢失,所以我们可以新增物品事件管理器类ItemEventManager ,动态的绑定相关事件到对应物品上

// 物品事件管理器类
public class ItemEventManager : Singleton<ItemEventManager>
{
    [SerializeField] private List<ItemReferences> itemReferences = new List<ItemReferences>(); // 物品引用列表

    // 获取物品事件
    public UnityEvent GetItemEvents(Item item)
    {
        ItemReferences itemRef = itemReferences.Find(x => x.item.name == item.name); // 查找物品引用
        return (itemRef != null && itemRef.events != null) ? itemRef.events : null; // 返回物品事件,如果为空则返回 null
    }
}

// 物品引用类
[System.Serializable]
public class ItemReferences
{
    public Item item; // 物品引用
    public UnityEvent events; // 物品事件
}

比如我们配置苹果使用可以加人物5饱食度和5水分值

修改Item,绑定对应的事件和使用物品功能

[Header("使用物品")]
public bool removeOneOnUse;// 是否是一次性物品
public UnityEvent myEvent;// 使用物品时触发的事件

private void Start()
{
    // 从物品事件管理器中获取该物品对应的物品事件
    UnityEvent newEvent = ItemEventManager.Instance.GetItemEvents(this);
    if (newEvent != null) myEvent = newEvent;
}

private void OnDisable()
{
    // 如果该物品不在场景中并且其使用物品事件没有任何持续事件,则直接返回
    if (!gameObject.scene.isLoaded || myEvent.GetPersistentEventCount() != 0) return;

    UnityEvent newEvent = ItemEventManager.Instance.GetItemEvents(this);
    if (newEvent != null) myEvent = newEvent;
}

//使用物品
public void UseItem()
{
    if (myEvent.GetPersistentEventCount() > 0)
    {
        myEvent.Invoke();// 触发使用物品事件
        if (removeOneOnUse) currentQuantity--;// 根据设置决定是否减少物品数量
    }
}

解释:

GetPersistentEventCount 是 Unity 中的方法,用于获取 UnityEvent 中持久化(persistent)事件的数量。在这里,它用于检查一个物品的使用事件中是否包含任何持久化的事件。

Unity 的事件系统允许您在编辑器中将方法绑定到事件,这些绑定在运行时会被称为“持久化”事件。GetPersistentEventCount 方法用于获取 UnityEvent 中已经绑定的持久化事件的数量,以便在代码中进行相应的逻辑处理。

在上述代码中,myEvent.GetPersistentEventCount() 用于检查 myEvent 中是否有持久化事件的绑定。如果事件绑定的数量不为 0,则说明该物品的使用事件已经被设置过,因此在禁用时不需要重新获取事件。


勾选苹果为一次性物品,及消耗品

修改Inventory

public void Update()
{
  //...
  
  if (Input.GetMouseButtonDown(0))
  {
      attemptToUseItem();//使用物品
  }
}

//使用物品
private void attemptToUseItem()
{
    if (curHotbarIndex == -1) return;
    Item curItem = hotbarSlots[curHotbarIndex].getItem();// 获取选中的快捷栏中的物品
    if (curItem && curItem.myEvent.GetPersistentEventCount() != 0)
    {
        curItem.UseItem();// 使用物品
        if (curItem.currentQuantity != 0)
            hotbarSlots[curHotbarIndex].updateData();// 更新快捷栏数据
        else
            hotbarSlots[curHotbarIndex].setItem(null);// 如果物品数量为0,清空快捷栏中的物品
        enableHotbarItem(curHotbarIndex);// 再次激活快捷栏中的物品
    }
}

效果

运行看物品事件是否绑定上了

拿在手上点击使用

源码

源码不出意外的话我会放在最后一节

目录
相关文章
|
4天前
|
存储 JSON 关系型数据库
【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解
【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解
15 2
|
4天前
|
图形学
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统(下)
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统
9 0
|
4天前
|
图形学 容器
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统(上)
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统
7 0
|
4天前
|
存储 JSON 图形学
【unity实战】制作unity数据保存和加载系统——小型游戏存储的最优解
【unity实战】制作unity数据保存和加载系统——小型游戏存储的最优解
6 0
|
5天前
|
图形学
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版3(附带项目源码)
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版3(附带项目源码)
16 2
|
5天前
|
图形学
【制作100个unity游戏之28】花半天时间用unity复刻童年4399经典小游戏《黄金矿工》(附带项目源码)
【制作100个unity游戏之28】花半天时间用unity复刻童年4399经典小游戏《黄金矿工》(附带项目源码)
17 0
|
5天前
|
图形学
【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)(上)
【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)
10 2
|
5天前
|
图形学
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版2(附带项目源码)
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版2(附带项目源码)
10 1
|
5天前
|
图形学
【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)(下)
【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)(下)
8 0
|
5天前
|
存储 JSON 关系型数据库
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版13(完结,附带项目源码)
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版13(完结,附带项目源码)
11 0