Unity游戲開發(fā)實(shí)現(xiàn)背包系統(tǒng)的示例詳解
引言
背包是游戲中經(jīng)常使用的一個(gè)組件,它負(fù)責(zé)管理玩家在游戲中所獲得的道具。一個(gè)完整的背包系統(tǒng)應(yīng)當(dāng)具有將物品放置進(jìn)背包、對(duì)背包內(nèi)物品進(jìn)行管理和使用背包內(nèi)物品等功能。而往往一個(gè)背包系統(tǒng)的邏輯關(guān)系較為復(fù)雜,如果把所有功能都放在一個(gè)腳本中實(shí)現(xiàn)會(huì)使代碼顯得十分冗雜且缺乏邏輯。所以在背包系統(tǒng)的設(shè)計(jì)過程中,我們常將其分解為數(shù)據(jù)、邏輯和UI三部分分別來進(jìn)行完成。
一、UI設(shè)計(jì)

以Cotton Puzzle中的背包設(shè)計(jì)為例,我們需要有物品展示欄、物品切換按鍵和物品提示信息等部分。

在Canvas中創(chuàng)建ItemHolder,在ItemHolder中創(chuàng)建LeftButton和RightButton控制物品的左右切換、Slot來控制物品的顯示以及ItemToolTip來顯示物品的提示信息。
二、UI
==創(chuàng)建InventoryUI腳本并掛在ItemHolder上以對(duì)整個(gè)背包UI進(jìn)行管理。== 首先,確定InventoryUI可以控制的組件并定義當(dāng)前所顯示的物品序號(hào),由于ItemToolTip的顯示與否和Slot直接相關(guān)聯(lián),所以可以通過控制Slot間接控制ItemToolTip,在InventoryUI中便不再單獨(dú)對(duì)其進(jìn)行控制。
//InventoryUI.cs
public Button leftButton;
public Button rightButton;
public SlotUI slotUI;
public int currentItemIndex;//當(dāng)前物品序號(hào)
2.1 Slot中的物品顯示
//InventoryUI.cs
/// <summary>
/// 更新Slot中物品圖片
/// </summary>
/// <param name="itemDetails"></param>
/// <param name="index"></param>
private void OnUpdateUIEvent(ItemDetails itemDetails, int index)
{
if (itemDetails == null)//當(dāng)前物品為空
{
slotUI.SetEmpty();
currentItemIndex = -1;
leftButton.interactable = false;
rightButton.interactable=false;
}
else
{
currentItemIndex = index;
slotUI.SetItem(itemDetails);
if (index > 0)
leftButton.interactable = true;
if (currentItemIndex == -1)
{
leftButton.interactable = false;
rightButton.interactable = false;
}
}
}
定義UpdateUIEvent事件來實(shí)時(shí)管理Slot中顯示的物品(通過調(diào)用SlotUI中實(shí)現(xiàn)的SetEmpty()和SetItem(itemDetails)方法實(shí)現(xiàn))和左右按鈕的可使用情況。
//InventoryUI.cs
private void OnEnable()
{
EventHandler.UpdateUIEvent += OnUpdateUIEvent;
}
private void OnDisable()
{
EventHandler.UpdateUIEvent -= OnUpdateUIEvent;
}
2.2 物品切換
//InventoryUI.cs
/// <summary>
/// 左右按鈕使用事件
/// </summary>
/// <param name="amount"></param>
public void SwitchItem(int amount)
{
var index = currentItemIndex + amount;
if(index< currentItemIndex)
{
leftButton.interactable = false;
rightButton.interactable = true;
}
else if(index> currentItemIndex)
{
leftButton.interactable = true;
rightButton.interactable = false;
}
else
{
leftButton.interactable = true;
rightButton.interactable = true;
}
EventHandler.CallChangeItemEvent(index);
}
2.3 SlotUI的實(shí)現(xiàn)
在SlotUI中需要實(shí)現(xiàn)將Slot圖片設(shè)置為指定物品(包含物品為空的情況)、鼠標(biāo)點(diǎn)擊反饋、鼠標(biāo)移入移出反饋(這里主要要實(shí)現(xiàn)當(dāng)鼠標(biāo)移入顯示物品文字描述信息,移出取消顯示的功能)。
//SlotUI.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class SlotUI : MonoBehaviour, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler
{
public Image itemImage;
public ItemDetails currentItem;
public ItemToolTip toolTip;
private bool isClicked;
/// <summary>
/// 設(shè)置Slot圖片為指定item
/// </summary>
/// <param name="itemDetails"></param>
public void SetItem(ItemDetails itemDetails)
{
currentItem = itemDetails;
this.gameObject.SetActive(true);
itemImage.sprite = itemDetails.itemSprite;
itemImage.SetNativeSize();
}
/// <summary>
/// 設(shè)置Slot圖片為空
/// </summary>
public void SetEmpty()
{
this.gameObject.SetActive(false);
}
public void OnPointerClick(PointerEventData eventData)
{
isClicked = !isClicked;
EventHandler.CallItemSelectedEvent(currentItem, isClicked);
}
public void OnPointerEnter(PointerEventData eventData)
{
if (this.gameObject.activeInHierarchy)
{
toolTip.gameObject.SetActive(true);
toolTip.UpdateItemName(currentItem.itemName);
}
}
public void OnPointerExit(PointerEventData eventData)
{
toolTip.gameObject.SetActive(false);
}
}
2.4 物品描述信息的展示
首先我們需要定義一個(gè)變量來記錄物品的信息。這里我們?cè)贗temToolTip下創(chuàng)建一個(gè)Text來記錄文本信息。
//ItemToolTip.cs
public Text itemNameText;
接下來定義方法根據(jù)目前Slot所展示的物品名字來修改Text的內(nèi)容。
//ItemToolTip.cs
public void UpdateItemName(ItemName itemName)
{
itemNameText.text = itemName switch
{
ItemName.Key => "信箱鑰匙",
ItemName.Ticket => "一張船票",
_ => ""
};
}
為了方便使用我們將物品名寫成了枚舉變量,定義在Enums腳本中,方便在其他腳本中也可以使用。
//Enums.cs
/// <summary>
/// 物品名
/// </summary>
public enum ItemName
{
None,
Key,
Ticket,
}
三、數(shù)據(jù)
首先為了我們能夠在unity中更加直觀地對(duì)數(shù)據(jù)進(jìn)行修改,利用以下代碼在unity的菜單下創(chuàng)建數(shù)據(jù)子菜單,并序列化對(duì)象。每個(gè)ItemDetails包含物品名(itemName)和物品貼圖(itemSprite)兩個(gè)屬性。
//ItemDataList.cs
[CreateAssetMenu(fileName ="ItemDataList",menuName = "Inventory/ItemDataList")]
/// <summary>
/// 對(duì)象序列化
/// </summary>
[System.Serializable]
public class ItemDetails
{
public ItemName itemName;
public Sprite itemSprite;
}
在unity中可以直接新建一個(gè)ItemDataList的數(shù)據(jù)對(duì)象,創(chuàng)建方式為:右鍵 -> Create ->Inventory -> ItemDataList

定義GetItemDetails根據(jù)物品名獲取ItemDetails 對(duì)象。
//ItemDataList.cs
public List<ItemDetails> itemDetailsList = new List<ItemDetails>();
public ItemDetails GetItemDetails(ItemName itemName)
{
return itemDetailsList.Find(i => i.itemName.Equals(itemName));
}
四、邏輯
對(duì)于場(chǎng)景中的物體,在鼠標(biāo)點(diǎn)擊后需要能夠被添加到背包內(nèi)并在原有位置消失。可通過ItemClicked()函數(shù)來實(shí)現(xiàn)。
//Item.cs
public ItemName itemName;
public void ItemClicked()
{
//隱藏鼠標(biāo)點(diǎn)擊物體
this.gameObject.SetActive(false);
//將物品添加到背包
InventoryManager.Instance.AddItem(itemName);
}
最后,需要定義一個(gè)腳本InventoryManager對(duì)背包系統(tǒng)的UI、數(shù)據(jù)進(jìn)行一個(gè)==統(tǒng)一的管理==。
//InventoryManager.cs
[SerializeField] private List<ItemName> itemList = new List<ItemName>();
public ItemDataList itemData;//通過物品名在物品列表中查找相應(yīng)物品
(1)在新加載游戲的時(shí)候需要清空物品列表
private void OnStartNewGameEvent(int gameWeek)
{
itemList.Clear();
}
(2)當(dāng)物品被使用時(shí)需要將物品移除背包并更新UI
private void OnItemUsedEvent(ItemName itemName)
{
var index = GetItemIndex(itemName);
itemList.RemoveAt(index);
if (itemList.Count == 0)
EventHandler.CallUpdateUIEvent(null, -1);
}
(3)當(dāng)場(chǎng)景加載之后,需要將目前背包中有的物品進(jìn)行更新
private void OnAfterSceneLoadedEvent()
{
if (itemList.Count == 0)
EventHandler.CallUpdateUIEvent(null, -1);
else
{
for (int i = 0; i < itemList.Count; i++)
{
EventHandler.CallUpdateUIEvent(itemData.GetItemDetails(itemList[i]), i);
}
}
}
(4)當(dāng)使用Button在背包中左右切換物品時(shí),需要實(shí)時(shí)更改物品的圖片并判斷是否越界
private void OnChangeItemEvent(int index)
{
if (index >= 0 && index < itemList.Count)
{
ItemDetails item = itemData.GetItemDetails(itemList[index]);
EventHandler.CallUpdateUIEvent(item, index);
}
else
{
Debug.Log("越界!");
}
}
注冊(cè)這些事件:
private void OnEnable()
{
EventHandler.ChangeItemEvent += OnChangeItemEvent;
EventHandler.AfterSceneLoadedEvent += OnAfterSceneLoadedEvent;
EventHandler.ItemUsedEvent += OnItemUsedEvent;
EventHandler.StartNewGameEvent += OnStartNewGameEvent;
}
private void OnDisable()
{
EventHandler.ChangeItemEvent -= OnChangeItemEvent;
EventHandler.AfterSceneLoadedEvent -= OnAfterSceneLoadedEvent;
EventHandler.ItemUsedEvent -= OnItemUsedEvent;
EventHandler.StartNewGameEvent -= OnStartNewGameEvent;
}
另外有一些工具函數(shù)需要實(shí)現(xiàn):
public void AddItem(ItemName itemName)
{
if(!itemList.Contains(itemName))//列表中不包含物品則添加到列表中
{
itemList.Add(itemName);
}
//UI顯示
EventHandler.CallUpdateUIEvent(itemData.GetItemDetails(itemName), itemList.Count - 1);
}
/// <summary>
/// 獲取物品在列表中的序號(hào)
/// </summary>
/// <param name="itemName"></param>
/// <returns></returns>
private int GetItemIndex(ItemName itemName)
{
for(int i=0;i<itemList.Count;i++)
{
if(itemName.Equals(itemList[i]))
return i;
}
return -1;
}以上就是Unity游戲開發(fā)實(shí)現(xiàn)背包系統(tǒng)的示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Unity游戲開發(fā)背包系統(tǒng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Unity中的RegisterPlugins實(shí)用案例深入解析
- Unity的IPostprocessBuild實(shí)用案例深入解析
- Unity的IPreprocessBuild實(shí)用案例深入解析
- Unity的IFilterBuildAssemblies實(shí)用案例深入解析
- Unity技術(shù)手冊(cè)之Button按鈕使用實(shí)例詳解
- Unity技術(shù)手冊(cè)之Slider滑動(dòng)器使用實(shí)例詳解
- Unity游戲開發(fā)實(shí)現(xiàn)場(chǎng)景切換示例
- Unity的BuildPlayerProcessor實(shí)用案例深入解析
相關(guān)文章
基于數(shù)據(jù)類型轉(zhuǎn)換(裝箱與拆箱)與常量詳解
下面小編就為大家分享一篇基于數(shù)據(jù)類型轉(zhuǎn)換(裝箱與拆箱)與常量詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2017-11-11
C#實(shí)現(xiàn)控制Windows系統(tǒng)關(guān)機(jī)、重啟和注銷的方法
這篇文章主要介紹了C#實(shí)現(xiàn)控制Windows系統(tǒng)關(guān)機(jī)、重啟和注銷的方法,涉及C#調(diào)用windows系統(tǒng)命令實(shí)現(xiàn)控制開機(jī)、關(guān)機(jī)等操作的技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-04-04
C# httpwebrequest訪問HTTPS錯(cuò)誤處理方法
下面小編就為大家?guī)硪黄狢# httpwebrequest訪問HTTPS錯(cuò)誤處理方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-01-01
詳解C#如何使用重載方法實(shí)現(xiàn)不同類型數(shù)據(jù)的計(jì)算
這篇文章主要為大家詳細(xì)介紹了C#如何使用重載方法實(shí)現(xiàn)不同類型數(shù)據(jù)的計(jì)算,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02
Unity實(shí)現(xiàn)多平臺(tái)二維碼掃描
這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)多平臺(tái)二維碼掃描,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07

