Unity模拟经营类游戏Demo部分代码及技术总结

本文总结了使用Unity制作的模拟经营类游戏Demo,涉及UI设计、库存系统、交易系统和游戏循环的实现。UI采用UGUI构建,库存系统包括Inventory、InventoryManager、Slot和ItemUI类,交易系统由购买和售卖面板组成,游戏循环借助 Animator Controller 的有限状态机完成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

7月份自己做了一个模拟经营类的游戏Demo,在此总结UI、库存系统、交易系统、游戏循环等相关内容的代码和实现。

实现效果预览

目录

UI

库存系统

交易系统

游戏循环


UI

本项目的UI通过Unity自家的UGUI实现,所有面板的父对象皆为Canvas,各面板为一个实例化的单例对象,其数据由自己进行存储和更新。

面板基础逻辑 

IPanel接口:

interface IPanel
{
    public void ShowPanel();

    public void HidePanel();
}

以商店面板为例:

(通过给面板添加CanvasGroup组件,并更改其参数实现面板的显隐)

public class ShopPanel : MonoBehaviour, IPanel
{
    //单例
    private static ShopPanel instance;
    public static ShopPanel Instance
    {
        get
        {
            return instance;
        }
    }

    //获取商店面板信息 
    public TMP_Text txtTime;
    public TMP_Text txtDays;
    public TMP_Text txtShopMoney;

    public KnapsackPanel knapsack1Panel;
    public KnapsackPanel knapsack2Panel;
    public KnapsackPanel knapsack3Panel;

    public RolePanel role1Panel;
    public RolePanel role2Panel;
    public RolePanel role3Panel;

    private CanvasGroup canvasGroup;
    
    private int money = 100;
    public int Money
    {
        get { return money; }
        set
        {
            money = value;
            txtShopMoney.text = money.ToString();
        }
    }

    public Button btnStorage;
    public Button btnCreate;

    public static bool storageVisible = false;
    public static bool createVisible = false;

    private void Awake()
    {
        //实例化单例
        instance = this;
    }

    // Start is called before the first frame update
    void Start()
    {
        canvasGroup = gameObject.GetComponent<CanvasGroup>();

        HidePanel();

        btnStorage.onClick.AddListener(() =>
        {
            //提示面板清空
            NoticePanel.Instance.HideNotice();

            //仓库按钮按下的逻辑
            if (!storageVisible)
            {
                storageVisible = true;
                StoragePanel.Instance.ShowPanel();
                createVisible = false;
                CreatePanel.Instance.HidePanel();
            }
            else
            {
                storageVisible = false;
                StoragePanel.Instance.HidePanel();
            }
        });

        btnCreate.onClick.AddListener(() =>
        {
            //提示面板清空
            NoticePanel.Instance.HideNotice();

            //制造按钮按下的逻辑
            if (!createVisible)
            {
                createVisible = true;
                CreatePanel.Instance.ShowPanel();
                storageVisible = false;
                StoragePanel.Instance.HidePanel();
            }
            else
            {
                createVisible = false;
                CreatePanel.Instance.HidePanel();
            }
        });

        txtShopMoney.text = money.ToString();
    }
    
    //实现接口IPanel
    public void ShowPanel()
    {
        canvasGroup.alpha = 1;
        canvasGroup.interactable = true;
        canvasGroup.blocksRaycasts = true;
    }

    public void HidePanel()
    {
        canvasGroup.alpha = 0;
        canvasGroup.interactable = false;
        canvasGroup.blocksRaycasts = false;
    }

    /// <summary>
    /// 花费金钱
    /// </summary>
    public bool ConsumeMoney(int amount)
    {
        if (money < amount)
        {
            NoticePanel.Instance.ShowNotice("金钱不足!");
            return false;
        }
        money -= amount;
        txtShopMoney.text = money.ToString();
        NoticePanel.Instance.ShowNotice("交易成功!");
        return true;
    }

    /// <summary>
    /// 赚取金钱
    /// </summary>
    public void EarnMoney(int amount)
    {
        money += amount;
        txtShopMoney.text = money.ToString();
    }
}

库存系统

库存系统由Inventory、InventoryManager、Slot、ItemUI等类实现。

Inventory类:

using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class Inventory : MonoBehaviour
{
    protected Slot[] slots;
    public Slot[] Slots
    {
        get
        {
            return slots;
        }

        set
        {
            slots = value;
        }
    }

    // Start is called before the first frame update
    public virtual void Start()
    {
        slots = GetComponentsInChildren<Slot>();
    }

    /// <summary>
    /// 通过ID存储物品
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public bool StoreItem(int id)
    {
        Item item = InventoryManager.Instance.GetItemID(id);
        return StoreItem(item);
    }

    /// <summary>
    /// 是否存储成功
    /// </summary>
    /// <param name="item"></param>
    /// <returns></returns>
    public bool StoreItem(Item item)
    {
        if (item == null)
            return false;

        if (item.capacity == 1)
        {
            Slot slot = FindEmptySlot();
            if (slot == null)
            {
                NoticePanel.Instance.ShowNotice("没空的物品槽!");
                return false;
            }
            else
            {
                slot.CreateItem(item);
            }
        }
        else
        {
            Slot slot = FindSameIDSlot(item);
            if (slot != null)
            {
                slot.CreateItem(item);
            }
            else //找新的空物品槽
            {
                Slot slot2 = FindEmptySlot();
                if (slot2 != null)
                    slot2.CreateItem(item);
                else
                {
                    NoticePanel.Instance.ShowNotice("没空的物品槽!");
                    return false;
                }
            }
        }
        return true;
    }

    /// <summary>
    /// 减少物品数量
    /// </summary>
    /// <param name="targetItem"></param>
    /// <param name="total"></param>
    /// <param name="amount"></param>
    /// <returns></returns>
    public bool ReduceItem(Item targetItem, int total, int amount = 1)
    {
        if (amount > total)
            return false;
        foreach (Slot slot in slots)
        {
            if (slot.transform.childCount != 0)
            {
                GameObject items = slot.transform.GetChild(0).GetComponent<ItemUI>().gameObject;
                if (items.GetComponent<ItemUI>().Item.id == targetItem.id)
                {
                    int currentAmount = int.Parse(items.transform.GetChild(0).gameObject.GetComponent<TMP_Text>().text);
                    if (amount >= currentAmount)
                    {
                        amount -= currentAmount;
                        total -= currentAmount;
                        items.transform.GetChild(0).gameObject.GetComponent<TMP_Text>().text = 0.ToString();
                        DestroyImmediate(items);
                        items = null;
                        if (total == 0)
                        {
                            BuyPanel.CancelBuy();
                            return true;
                        }
                    }
                    else
                    {
                        currentAmount -= amount;
                        total -= amount;
                        items.GetComponent<ItemUI>().Amount = currentAmount;
                        items.transform.GetChild(0).gameObject.GetComponent<TMP_Text>().text = currentAmount.ToString();
                        amount = 0;
                    }
                }
                if (amount == 0)
                {
                    return true;
                }
            }
        }
        return false;
    }

    /// <summary>
    /// 找空的物品槽
    /// </summary>
    /// <returns></returns>
    private Slot FindEmptySlot()
    {
        foreach (Slot slot in slots)
        {
            if (slot.transform.childCount == 0)
                return slot;
        }
        return null;
    }

    /// <summary>
    /// 找相同ID的物品槽
    /// </summary>
    /// <returns></returns>
    private Slot FindSameIDSlot(Item item)
    {
        foreach (Slot slot in slots)
        {
            if (slot.transform.childCount >= 1 && slot.GetItemID() == item.id && slot.IsFull() == false)
                return slot;
        }
        return null;
    }

    /// <summary>
    /// 统计相同ID物品的总数量
    /// </summary>
    /// <param name="item"></param>
    /// <returns></returns>
    public int CountSameIDSlot(Item item)
    {
        int count = 0;
        foreach (Slot slot in slots)
        {
            if (slot.transform.childCount >= 1 && slot.GetItemID() == item.id)
                count += int.Parse(slot.transform.GetChild(0).transform.GetChild(0).GetComponent<TMP_Text>().text);
        }
        return count;
    }

    /// <summary>
    /// 背包整理(空格收纳、物品排序、材料收纳)
    /// </summary>
    public void InventoryClear()
    {
        EmptyClear();
        Sort();
        Combine();
    }

    /// <summary>
    /// 空格收纳
    /// </summary>
    public void EmptyClear()
    {
        int itemCount = 0;
        foreach(Slot slot in slots)
        {
            if (slot.transform.childCount != 0)
                itemCount++;
        }
        for (int i = 0; i < slots.Length; i++)
        {
            if (slots[i].transform.childCount == 0)
            {
                OneEmptyClear(i);
                i = -1;
            }
            if (i + 1 == itemCount)
                return;
        }
    }

    /// <summary>
    /// 单个空格收纳
    /// </summary>
    /// <param name="index"></param>
    public void OneEmptyClear(int index)
    {
        for (int i = index + 1; i < slots.Length; i++)
        {
            if (slots[i].transform.childCount != 0)
            {
                GameObject go1 = slots[i].transform.Find("Items(Clone)").gameObject;
                go1.transform.SetParent(slots[i - 1].transform);
                go1.transform.localPosition = Vector3.zero;
            }
        }
    }

    /// <summary>
    /// 物品排序
    /// </summary>
    public void Sort()
    {
        //整体排序
        int i, j;
        for (i = 0; i < slots.Length - 1; i++)
        {
            if (slots[i].transform.childCount == 0)
                break;
            for (j = i + 1; j < slots.Length; j++)
            {
                if (slots[j].transform.childCount == 0)
                    break;
                if (slots[i].transform.GetChild(0).GetComponent<ItemUI>().Item.id < slots[j].transform.GetChild(0).GetComponent<ItemUI>().Item.id)
                {
                    Swap(i, j);
                }
            }
        }

        int l = 0;
        int k = l;
        //装备耐久度排序(优先低耐久度)
        while (slots[l].transform.childCount != 0 && slots[l].transform.GetChild(0).GetComponent<ItemUI>().Item.type == Item.ItemType.Equipment)
        {
            while (slots[k].transform.childCount != 0 && slots[k].transform.GetChild(0).GetComponent<ItemUI>().Item.id == slots[l].transform.GetChild(0).GetComponent<ItemUI>().Item.id)
                k++;
            for (i = l; i < k - 1; i++)
            {
                for (j = i + 1; j < k; j++)
                {
                    if (slots[i].transform.GetChild(0).GetComponent<ItemUI>().durability > slots[j].transform.GetChild(0).GetComponent<ItemUI>().durability)
                    {
                        Swap(i, j);
                    }
                }
            }
            l = k;
        }
    }

    /// <summary>
    /// 交换物品位置
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    public void Swap(int a, int b)
    {
        GameObject go1 = slots[a].transform.Find("Items(Clone)").gameObject;
        GameObject go2 = slots[b].transform.Find("Items(Clone)").gameObject;
        go1.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值