本篇文章完成Inventory的控制,即控制所有的背包的UI跟数据(Player Bag,Box,Shop)的连接断句的代码
基本流程
1.代码思路
首先,在控制人物背包时,需要考虑到钱数,以及所有格子,
其次,创建的代码肯定是属于背包系统的同一个命名空间内的,
创建代码后,第一,拿到所有的格子,以便更新(UpdateSlot),
每个SlotUI中itemDetails和PlayerBag(Inventory Bag_SO)忘了这个数据结构的参考这个文章中的数据是一一对应的,那既然相互对应,那么PlayerBag的数组容量将永远是26个(为什么是26,因为这个大小是我自己设计的,我的ActionBar和PalyerBag的Slot之和是26)
2. 代码实现
using System.Collections;
using System.Collections.Generic;
using UnityEngine;namespace FuliFarm.Inventory {public class InventoryUI : MonoBehaviour{//在Unity中设置时考虑的优先级是(底部的ActionBar > PalyerBag)//例:在地上拾取物品时优先添加到ActionBar中,等ActionBar满后,才添加到玩家背包中[SerializeField] private SlotUI[] playerSlots;//注册好事件了,去InventoryManager中的AddItem里呼叫private void OnEnable(){EventHandler.UpdateInventoryUI += OnUpdateInventoryUI;}private void OnDisable(){EventHandler.UpdateInventoryUI -= OnUpdateInventoryUI;}public void Start(){//给每个格子一个序号,序号和背包中顺序一致for (int i = 0; i < playerSlots.Length;i++){playerSlots[i].slotIndex = i;}}private void OnUpdateInventoryUI(InventoryLocation location, List<InventoryItem> list){switch (location){case InventoryLocation.Player:for (int i = 0; i < playerSlots.Length; i++){if (list[i].itemAmount > 0){var item = InventoryManager.Instance.GetItemDetails(list[i].itemID);playerSlots[i].UpdateSlot(item, list[i].itemAmount);}else {playerSlots[i].UpdateEmptySlot();}}break;}}}
}
更新InventoryManager中的AddItem函数以及新增start函数
public void AddItem(Item item ,bool toDestroy)
{//背包是不是已经有这个物品var index = GetItemIndexInBag(item.itemID);AddItemAtIndex(item.itemID,index,1);Debug.Log(GetItemDetails(item.itemID).itemID + "Name: " + GetItemDetails(item.itemID).itemName);if (toDestroy) {Destroy(item.gameObject);}//更新UIEventHandler.CallUpdateInventoryUI(InventoryLocation.Player,playerBag.itemList);
}
[Header("背包数据")]
public InventoryBag_SO playerBag;private void Start()
{EventHandler.CallUpdateInventoryUI(InventoryLocation.Player, playerBag.itemList);
}
增加Enum的枚举类
public enum InventoryLocation
{Player,Box
}
新增用于处理事件的脚本
//事件中心
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public static class EventHandler//改为静态类,方便随时调用
{//注册事件public static event Action<InventoryLocation, List<InventoryItem>> UpdateInventoryUI;//<哪个地方的库存,什么数据>,在InventoryUI中更新//调用事件public static void CallUpdateInventoryUI(InventoryLocation location, List<InventoryItem> list){UpdateInventoryUI?.Invoke(location, list);}}
将所有有关的SlotBag预制体按ActionBar,playerBag的顺序拖入到PlayerBag的Player Slots里,这样可以保证拾取物品后先填充的是ActionBar,直到ActionBar填充完后, 再去填充背包
最终效果
最初读取效果如下:因为我的PlayerBag里此时还没有东西
初始PlayerBag
运行游戏后,操作角色去获得地图中的可拾取物品,优先填充到ActionBar中
PlayerBag同步更新
补充知识点
1.OnEnable函数
看这篇文章
2.OnEnable、Awake、Start之间的区别
- Awake
- 调用时机:Awake 函数在脚本实例被加载时调用,是整个生命周期中最早被调用的函数之一。通常在对象被实例化后,就会立刻执行 Awake 函数。例如,当一个游戏场景中的游戏对象(GameObject)被加载时,附加在该对象上的脚本中的 Awake 函数就会被调用。
- 执行特点:在场景加载时,所有脚本的 Awake 函数会按照它们在场景中的加载顺序依次执行。而且,Awake 函数只会被调用一次,即使游戏对象被禁用(SetActive (false))然后再启用,Awake 函数也不会再次执行。例如,在一个包含多个敌人角色的游戏场景中,每个敌人脚本的 Awake 函数会在场景加载时执行一次,用于初始化一些基本的属性,如敌人的初始生命值、攻击力等基本参数。
- 典型用途:主要用于初始化脚本所需的引用,如获取其他游戏对象的引用,或者初始化一些不会在游戏过程中改变的变量。例如,在一个射击游戏中,通过 Awake 函数获取玩家角色的引用,以便后续的脚本能够访问玩家的位置、状态等信息。
- Start
- 调用时机:Start 函数在 Awake 函数之后调用,但是它会在所有脚本的 Awake 函数执行完之后才开始执行。具体来说,是在脚本所在的游戏对象被启用(SetActive (true))后,并且在 Update 函数第一次调用之前被调用。例如,当游戏场景加载完成后,场景中的游戏对象都已经完成了 Awake 阶段的初始化,然后每个对象的 Start 函数就会按照顺序执行。
- 执行特点:和 Awake 函数一样,Start 函数也只会被调用一次。它在整个游戏对象的生命周期中只在初始化阶段调用一次,用于一些需要在 Awake 之后进行的初始化操作。例如,在一个赛车游戏中,赛车对象的脚本可以在 Awake 函数中初始化一些基本组件,如车轮碰撞器等,然后在 Start 函数中设置赛车的初始速度等参数。
- 典型用途:通常用于依赖于其他脚本初始化完成后的操作。比如,在一个角色扮演游戏中,角色的技能系统可能需要在角色自身的基本属性(通过 Awake 初始化)以及其他相关系统(如游戏的战斗管理器,通过其他脚本的 Awake 初始化)初始化完成后,在 Start 函数中进行技能列表的初始化和相关参数的设置。
- OnEnable
- 调用时机:OnEnable 函数在游戏对象从禁用状态变为启用状态时被调用。这可能是因为游戏对象初始时是禁用的,后来被启用,或者是因为它在运行过程中被多次禁用和启用。例如,在一个关卡游戏中,有一些隐藏的道具箱,当玩家触发某个条件后,道具箱游戏对象从禁用状态变为启用状态,此时附加在道具箱上的脚本中的 OnEnable 函数就会被调用。
- 执行特点:与 Awake 和 Start 不同,OnEnable 函数可以被多次调用。每次游戏对象从禁用变为启用时,它都会被调用。这使得它非常适合用于处理游戏对象启用时需要进行的动态初始化或者重置操作。例如,一个敌人对象被玩家击败后,可能会被设置为禁用状态,当游戏中的复活机制触发使这个敌人再次启用时,OnEnable 函数就可以用于重置敌人的状态,如恢复生命值、重新初始化行为树等操作。
- 典型用途:用于在游戏对象每次启用时重新初始化组件状态、订阅事件或者重置一些变量。例如,在一个 UI 界面系统中,当一个弹出式菜单被启用时,通过 OnEnable 函数可以重新初始化菜单中的选项状态,订阅相关的按钮点击事件等操作。
还是不懂看这个