Unity游戲開發(fā)實(shí)現(xiàn)背包系統(tǒng)的示例詳解
引言
背包是游戲中經(jīng)常使用的一個(gè)組件,它負(fù)責(zé)管理玩家在游戲中所獲得的道具。一個(gè)完整的背包系統(tǒng)應(yīng)當(dāng)具有將物品放置進(jìn)背包、對背包內(nèi)物品進(jìn)行管理和使用背包內(nèi)物品等功能。而往往一個(gè)背包系統(tǒng)的邏輯關(guān)系較為復(fù)雜,如果把所有功能都放在一個(gè)腳本中實(shí)現(xiàn)會使代碼顯得十分冗雜且缺乏邏輯。所以在背包系統(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上以對整個(gè)背包UI進(jìn)行管理。== 首先,確定InventoryUI可以控制的組件并定義當(dāng)前所顯示的物品序號,由于ItemToolTip的顯示與否和Slot直接相關(guān)聯(lián),所以可以通過控制Slot間接控制ItemToolTip,在InventoryUI中便不再單獨(dú)對其進(jìn)行控制。
//InventoryUI.cs public Button leftButton; public Button rightButton; public SlotUI slotUI; public int currentItemIndex;//當(dāng)前物品序號
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è)變量來記錄物品的信息。這里我們在ItemToolTip下創(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中更加直觀地對數(shù)據(jù)進(jìn)行修改,利用以下代碼在unity的菜單下創(chuàng)建數(shù)據(jù)子菜單,并序列化對象。每個(gè)ItemDetails包含物品名(itemName)和物品貼圖(itemSprite)兩個(gè)屬性。
//ItemDataList.cs [CreateAssetMenu(fileName ="ItemDataList",menuName = "Inventory/ItemDataList")] /// <summary> /// 對象序列化 /// </summary> [System.Serializable] public class ItemDetails { public ItemName itemName; public Sprite itemSprite; }
在unity中可以直接新建一個(gè)ItemDataList的數(shù)據(jù)對象,創(chuàng)建方式為:右鍵 -> Create ->Inventory -> ItemDataList
定義GetItemDetails根據(jù)物品名獲取ItemDetails 對象。
//ItemDataList.cs public List<ItemDetails> itemDetailsList = new List<ItemDetails>(); public ItemDetails GetItemDetails(ItemName itemName) { return itemDetailsList.Find(i => i.itemName.Equals(itemName)); }
四、邏輯
對于場景中的物體,在鼠標(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對背包系統(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)場景加載之后,需要將目前背包中有的物品進(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("越界!"); } }
注冊這些事件:
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> /// 獲取物品在列表中的序號 /// </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)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
基于數(shù)據(jù)類型轉(zhuǎn)換(裝箱與拆箱)與常量詳解
下面小編就為大家分享一篇基于數(shù)據(jù)類型轉(zhuǎn)換(裝箱與拆箱)與常量詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-11-11C#實(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ī)等操作的技巧,非常簡單實(shí)用,需要的朋友可以參考下2015-04-04C# httpwebrequest訪問HTTPS錯誤處理方法
下面小編就為大家?guī)硪黄狢# httpwebrequest訪問HTTPS錯誤處理方法。小編覺得挺不錯的,現(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