欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Unity游戲開發(fā)實(shí)現(xiàn)背包系統(tǒng)的示例詳解

 更新時(shí)間:2022年08月11日 16:41:18   作者:lucky_  
這篇文章主要為大家介紹了Unity游戲開發(fā)實(shí)現(xiàn)背包系統(tǒng)的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

背包是游戲中經(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);
    }
    /// &lt;summary&gt;
    /// 獲取物品在列表中的序號
    /// &lt;/summary&gt;
    /// &lt;param name="itemName"&gt;&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    private int GetItemIndex(ItemName itemName)
    {
        for(int i=0;i&lt;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)文章

最新評論