当前位置:网站首页>Unity 高級背包系統
Unity 高級背包系統
2022-06-11 04:20:00 【海 月】
前言
之前實現了一個初級的背包系統,它沒有對物品進行分類。
這一次新增了物品的分類存儲與顯示。
Asset的結構
為了對物品進行分類管理,在ScriptableObject中使用列錶存儲三個類型的物品,分別是武器、食物以及材料。這個列錶中的元素是一個特別的類,它包含了這類物品的名字,以及存儲這類物品的列錶。在物品配置錶中,存儲的是Item類對象,在背包物品數據錶中,存儲的是InventoryItem對象,它們的差异是,InventoryItem類的對象多了一個數量的屬性。


物品的編號
101~199 是武器
201~299 是食物
301~399 是材料
判斷物品的類型,用物品的 index / 100 即可。
代碼
物品配置錶
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu]
public class ItemsConfigurationAdvanced : ScriptableObject
{
[Header("物品分類列錶")]
public List<ItemList> lists;
}
[System.Serializable]
public class ItemList
{
public string listName;
public List<Item> items;
}背包物品配置錶
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu]
public class InventoryConfigurationAdvanced : ScriptableObject
{
[Header("玩家持有物品的分類列錶")]
public List<InventoryItemList> lists;
}
[System.Serializable]
public class InventoryItemList
{
public string listName;
public List<InventoryItem> items;
public InventoryItemList(string name)
{
listName = name;
items = new List<InventoryItem>();
}
}背包物品類
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[Serializable]
public class InventoryItem : Item
{
public int num;
public InventoryItem(Item item, int num) : base(item)
{
this.num = num;
}
}注:背包物品類的構造函數調用了基類的拷貝構造函數
物品類
using System;
using UnityEngine;
using UnityEngine.UI;
[Serializable]
public class Item
{
public int id;
public string name;
public string description;
public Texture2D icon;
public GameObject model;
public Item(Item item)
{
id = item.id;
name = item.name;
description = item.description;
icon = item.icon;
model = item.model;
}
}物品數據管理器
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 提供物品配置錶與背包物品
/// </summary>
public class BackpackManagerAdvanced : Singleton<BackpackManagerAdvanced>
{
public ItemsConfigurationAdvanced itemsConfiguration = Resources.Load<ItemsConfigurationAdvanced>("Configurations/Items Configuration Advanced");
public InventoryConfigurationAdvanced inventoryConfiguration = Resources.Load<InventoryConfigurationAdvanced>("Configurations/Inventory Configuration Advanced");
/// <summary>
/// 從背包中獲取指定編號的物品
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
InventoryItem Contains(int index)
{
if (inventoryConfiguration.lists == null)
{
inventoryConfiguration.lists = new List<InventoryItemList>();
}
if(inventoryConfiguration.lists[index / 100 - 1] == null)
{
inventoryConfiguration.lists[index / 100 - 1] = new InventoryItemList(itemsConfiguration.lists[index / 100 - 1].listName);
}
foreach (var i in inventoryConfiguration.lists[index / 100 - 1].items)
{
if (i.id == index)
return i;
}
return null;
}
/// <summary>
/// 保存指定編號的物品到背包
/// </summary>
/// <param name="index"></param>
public void SaveItemToInventory(int index)
{
InventoryItem temp = Contains(index);
if (temp != null)
temp.num++;
else
inventoryConfiguration.lists[index / 100 - 1].items.Add(new InventoryItem(GetItem(index), 1));
}
/// <summary>
/// 從物品配置錶中獲取指定編號的物品
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public Item GetItem(int index)
{
foreach (var i in itemsConfiguration.lists[index / 100 - 1].items)
{
if (i.id == index)
return i;
}
return null;
}
}背包面板類
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class BackpackPanel : BasePanel
{
static readonly string path = "Prefabs/UI/BackpackPanel";
public BackpackPanel() : base(new PanelType(path)) { }
/*-----------可配置的參數-----------*/
public int column = 5; //列數
public float itemSize = 280; //物品格子大小
public float interval = 20; //格子之間的間隙
public float viewPortHeight = 1500; //窗口的高度
//記錄上一次顯示的最值索引,以便移除看不見的格子
int lastMinDisplayIndex;
int lastMaxDisplayIndex;
//滑動列錶的容器
public RectTransform content;
//存儲當前顯示的格子及編號
Dictionary<int, GameObject> curDisplayGrids = new Dictionary<int, GameObject>();
public Item selectedItem;//當前選中的物品
public override void OnEnter()
{
panelBindingTool.GetOrAddComponentInChildren<Button>("關閉").onClick.AddListener(() =>
{
panelStack.Pop();
}
);
panelBindingTool.GetOrAddComponentInChildren<Button>("詳情").onClick.AddListener(() =>
{
panelStack.Push(new ItemDetailPanel(selectedItem));
}
);
panelBindingTool.GetOrAddComponentInChildren<Button>("武器").onClick.AddListener(() =>
{
listIndex = 1;
InitThisTypeOfBackpack();
}
);
panelBindingTool.GetOrAddComponentInChildren<Button>("食物").onClick.AddListener(() =>
{
listIndex = 2;
InitThisTypeOfBackpack();
}
);
panelBindingTool.GetOrAddComponentInChildren<Button>("材料").onClick.AddListener(() =>
{
listIndex = 3;
InitThisTypeOfBackpack();
}
);
InitThisTypeOfBackpack();
OrbitCamera.Instance.work = false;
}
int listIndex = 1;//當前顯示的物品分類 100~199 武器 200~299 食物 300~399 材料
void InitThisTypeOfBackpack()
{
DestroyCurDisplayGrids();
content = panelBindingTool.GetOrAddComponentInChildren<RectTransform>("Content"); //獲取容器的組件
content.sizeDelta = new Vector2(0, Mathf.CeilToInt(BackpackManagerAdvanced.Instance.inventoryConfiguration.lists[listIndex-1].items.Count / column) * (itemSize + interval)); //根據物品數目計算容器的高度(向上取整)
GameManager.Instance.listIndex = listIndex;
GameManager.Instance.MethodField = DisplayBackpackGridAdvanced; //將DisplayBagItem函數注入GameManager的Update中,實現實時更新
//初始顯示第一個物品
DisplayItemBeief(BackpackManagerAdvanced.Instance.inventoryConfiguration.lists[listIndex-1].items[0]);
selectedItem = BackpackManagerAdvanced.Instance.inventoryConfiguration.lists[listIndex-1].items[0];
}
void DestroyCurDisplayGrids()
{
for(int i = 0;i<curDisplayGrids.Count;i++)
{
GameObject.Destroy(curDisplayGrids[i]);
}
curDisplayGrids.Clear();
lastMinDisplayIndex = 0;
lastMaxDisplayIndex = 0;
}
//銷毀正在顯示的格子並初始化相關參數
public override void OnExit()
{
GameManager.Instance.NonMonoUpdateMethod = null; //取消注入
GameManager.Instance.MethodField = null; //取消注入
panelManager.DestroyPanel(this.panelType);
OrbitCamera.Instance.work = true;
}
public override void OnPause()
{
panelBindingTool.GetOrAddComponent<CanvasGroup>().blocksRaycasts = false;
}
public override void OnResume()
{
panelBindingTool.GetOrAddComponent<CanvasGroup>().blocksRaycasts = true;
}
public void DisplayItemBeief(Item item)
{
panelBindingTool.GetOrAddComponentInChildren<Text>("Item Name").text = item.name;
panelBindingTool.GetOrAddComponentInChildren<Text>("Item Description").text = item.description;
panelBindingTool.GetOrAddComponentInChildren<Image>("Item Image").sprite = Sprite.Create(item.icon, new Rect(0, 0, item.icon.width, item.icon.height), new Vector2(0.5f, 0.5f));
}
public void DisplayBackpackGridAdvanced(int listIndex)
{
/*-----------計算可見範圍-----------*/
int minDisplayIndex = (int)(content.anchoredPosition.y / (itemSize + interval)) * column; //向下取整: 0,0 190,3 950,15
int maxDisplayIndex = (int)((content.anchoredPosition.y + viewPortHeight) / (itemSize + interval)) * column + column; // 下面一欄物品,露出一點點也需要顯示,所以需要多顯示一行
/*-----------越界的不顯示-----------*/
if (minDisplayIndex < 0)
minDisplayIndex = 0;
if (maxDisplayIndex > BackpackManagerAdvanced.Instance.inventoryConfiguration.lists[listIndex-1].items.Count)
maxDisplayIndex = BackpackManagerAdvanced.Instance.inventoryConfiguration.lists[listIndex-1].items.Count;
/*---------顯示可見範圍內的格子------*/
for (int i = minDisplayIndex; i < maxDisplayIndex; i++)
{
if (curDisplayGrids.ContainsKey(i)) //已顯示的格子,不再重複創建
continue;
else
{
GameObject obj = PoolManager.Instance.getObject("BackpackGrid", "Prefabs/UI/BackpackGrid"); //未顯示的格子,從池中獲取
obj.transform.SetParent(content);
obj.transform.localPosition = new Vector3(i % column * (itemSize + interval), i / column * (itemSize + interval) * (-1), 0); //將格子放到正確的比特置上
obj.GetComponent<BackpackGrid>().InitInfo(BackpackManagerAdvanced.Instance.inventoryConfiguration.lists[listIndex-1].items[i]); //初始化格子信息
obj.GetComponent<BackpackGrid>().OnClick(this, BackpackManagerAdvanced.Instance.inventoryConfiguration.lists[listIndex-1].items[i]);
curDisplayGrids[i] = obj; //將當前顯示的格子按照編號錄入字典
}
}
/*----------移除不可見的格子---------*/
for (int i = lastMaxDisplayIndex; i > maxDisplayIndex; i--)
{
if (curDisplayGrids.ContainsKey(i))
{
PoolManager.Instance.recycleObject("BackpackGrid", curDisplayGrids[i]);
curDisplayGrids.Remove(i);
}
}
for (int i = lastMinDisplayIndex; i < minDisplayIndex; i++)
{
if (curDisplayGrids.ContainsKey(i))
{
PoolManager.Instance.recycleObject("BackpackGrid", curDisplayGrids[i]);
curDisplayGrids.Remove(i);
}
}
lastMaxDisplayIndex = maxDisplayIndex;
lastMinDisplayIndex = minDisplayIndex;
}
}效果

边栏推荐
- Fundamentals of embedded audio processing
- Unity prefab scene conflict merge tool unityyamlmerge
- Final review of software engineering notes (short answer)
- FreeRTOS startup - based on stm32
- 数据分析师必知必会的统计学知识
- Guanghetong won the "science and Technology Collaboration Award" of Hello travel, driving two rounds of green industries to embrace digital intelligence transformation
- 域名解析耗时是什么?域名解析耗时影响因素有哪些?
- 27 pieces of advice for communication young people
- Eth Of Erc20 And Erc721
- 司马炎爷爷 告诉你什么叫做内卷!
猜你喜欢

Eth Transfer

Given a project, how will you conduct performance testing?

MySQL stored procedure

店铺门面转让出租小程序开发制作功能介绍

直播助力杭州电商独角兽冲击上市,分账系统重构电商交易新格局

Unity 可缩放地图的制作

七个好用的装饰器

L'avenir est venu, l'ère 5G - Advanced s'ouvre

CES 2022 𞓜 guanghetong LTE module fm101 has obtained two important ce/fcc certifications with excellent performance

MySql索引
随机推荐
Market prospect analysis and Research Report of nitrogen liquefier in 2022
Talk about data center network again
JVM(2):内存结构、类的加载过程
ESP series module burning firmware
golang泛型:generics
Grandpa simayan told you what is called inside roll!
Pictures that make people feel calm and warm
2022 love analysis · privacy computing vendor panoramic report | love Analysis Report
Guanghetong won the "science and Technology Collaboration Award" of Hello travel, driving two rounds of green industries to embrace digital intelligence transformation
Matter protocol
零时科技 | Discover 闪电贷攻击事件分析
App live broadcast source code, platform login page and password modification page
Esp32 development -lvgl uses internal and external fonts
Some differences between people
FreeRTOS startup - based on stm32
Eth Of Erc20 And Erc721
Evil CSRF
Possible problems with password retrieval function (supplementary)
B - wall painting (C language)
PHP正则用例