Unity游戏开发实现背包系统的示例详解

目录
  • 引言
  • 一、UI设计
  • 二、UI
    • 2.1 Slot中的物品显示
    • 2.2 物品切换
    • 2.3 SlotUI的实现
    • 2.4 物品描述信息的展示
  • 三、数据
  • 四、逻辑

引言

背包是游戏中经常使用的一个组件,它负责管理玩家在游戏中所获得的道具。一个完整的背包系统应当具有将物品放置进背包、对背包内物品进行管理和使用背包内物品等功能。而往往一个背包系统的逻辑关系较为复杂,如果把所有功能都放在一个脚本中实现会使代码显得十分冗杂且缺乏逻辑。所以在背包系统的设计过程中,我们常将其分解为数据、逻辑和UI三部分分别来进行完成。

一、UI设计

以Cotton Puzzle中的背包设计为例,我们需要有物品展示栏、物品切换按键和物品提示信息等部分。

在Canvas中创建ItemHolder,在ItemHolder中创建LeftButton和RightButton控制物品的左右切换、Slot来控制物品的显示以及ItemToolTip来显示物品的提示信息。

二、UI

==创建InventoryUI脚本并挂在ItemHolder上以对整个背包UI进行管理。== 首先,确定InventoryUI可以控制的组件并定义当前所显示的物品序号,由于ItemToolTip的显示与否和Slot直接相关联,所以可以通过控制Slot间接控制ItemToolTip,在InventoryUI中便不再单独对其进行控制。

//InventoryUI.cs
    public Button leftButton;
    public Button rightButton;
    public SlotUI slotUI;
    public int currentItemIndex;//当前物品序号

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)//当前物品为空
        {
            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事件来实时管理Slot中显示的物品(通过调用SlotUI中实现的SetEmpty()和SetItem(itemDetails)方法实现)和左右按钮的可使用情况。

//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的实现

在SlotUI中需要实现将Slot图片设置为指定物品(包含物品为空的情况)、鼠标点击反馈、鼠标移入移出反馈(这里主要要实现当鼠标移入显示物品文字描述信息,移出取消显示的功能)。

//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>
    /// 设置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>
    /// 设置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 物品描述信息的展示

首先我们需要定义一个变量来记录物品的信息。这里我们在ItemToolTip下创建一个Text来记录文本信息。

//ItemToolTip.cs
    public Text itemNameText;

接下来定义方法根据目前Slot所展示的物品名字来修改Text的内容。

//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,
}

三、数据

首先为了我们能够在unity中更加直观地对数据进行修改,利用以下代码在unity的菜单下创建数据子菜单,并序列化对象。每个ItemDetails包含物品名(itemName)和物品贴图(itemSprite)两个属性。

//ItemDataList.cs
[CreateAssetMenu(fileName ="ItemDataList",menuName = "Inventory/ItemDataList")]
/// <summary>
/// 对象序列化
/// </summary>
[System.Serializable]
public class ItemDetails
{
    public ItemName itemName;
    public Sprite itemSprite;
}

在unity中可以直接新建一个ItemDataList的数据对象,创建方式为:右键 -> Create ->Inventory -> ItemDataList

定义GetItemDetails根据物品名获取ItemDetails 对象。

//ItemDataList.cs
    public List<ItemDetails> itemDetailsList = new List<ItemDetails>();
    public ItemDetails GetItemDetails(ItemName itemName)
    {
        return itemDetailsList.Find(i => i.itemName.Equals(itemName));
    }

四、逻辑

对于场景中的物体,在鼠标点击后需要能够被添加到背包内并在原有位置消失。可通过ItemClicked()函数来实现。

//Item.cs
    public ItemName itemName;
    public void ItemClicked()
    {
        //隐藏鼠标点击物体
        this.gameObject.SetActive(false);
        //将物品添加到背包
        InventoryManager.Instance.AddItem(itemName);
    }

最后,需要定义一个脚本InventoryManager对背包系统的UI、数据进行一个==统一的管理==。

//InventoryManager.cs
    [SerializeField] private List<ItemName> itemList = new List<ItemName>();
    public ItemDataList itemData;//通过物品名在物品列表中查找相应物品

(1)在新加载游戏的时候需要清空物品列表

    private void OnStartNewGameEvent(int gameWeek)
    {
        itemList.Clear();
    }

(2)当物品被使用时需要将物品移除背包并更新UI

    private void OnItemUsedEvent(ItemName itemName)
    {
        var index = GetItemIndex(itemName);
        itemList.RemoveAt(index);
        if (itemList.Count == 0)
            EventHandler.CallUpdateUIEvent(null, -1);
    }

(3)当场景加载之后,需要将目前背包中有的物品进行更新

    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)当使用Button在背包中左右切换物品时,需要实时更改物品的图片并判断是否越界

    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;
    }

另外有一些工具函数需要实现:

    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游戏开发实现背包系统的示例详解的详细内容,更多关于Unity游戏开发背包系统的资料请关注我们其它相关文章!

(0)

相关推荐

  • Unity游戏开发之2048游戏的实现

    目录 一.前言 二.游戏开发知识储备 2-1技术栈 三.休闲类游戏<2048>开发实战 3-1玩法概述 3-2实现分析 3-3搭建场景 3-4实现代码 一.前言 写今天这篇文章的缘由,其实是来自于前段时间和粉丝的一个聊天,最近他打算参加游戏创作大赛,问我需要准备学习什么知识,以及参加比赛的注意事项一类: 我相信因为热爱游戏而前来投身于U3D学习的粉丝想来不是少数,兴趣可以驱动学习,在完善自己心爱游戏的过程中,要不断的去学习,不断的提高自己. 而参与游戏设计比赛,更是提高自身技术实力.增长眼界见

  • 基于Unity3D实现3D迷宫小游戏的示例代码

    目录 一.前言 二.构思 三.正式开发 3-1.搭建场景 3-2.设置出入口 3-3.添加角色 3-4.实现角色移动 3-5.出入口逻辑 四.总结 一.前言 闲来无事,从零开始整个<3D迷宫>小游戏. 本篇文章会详细介绍构思.实现思路,希望可以帮助到有缘人. 二.构思 首先,要实现一个小游戏,心里肯定要有一个大概的想法,然后就是将想法完善起来. 我的想法就是一个用立体的墙搭建的迷宫,然后控制人物在迷宫中移动,最后找到出口,就这么简单. 当然,这是一个雏形,比如可以加点音效.背景.关卡.解密等.

  • Unity游戏开发实现场景切换示例

    目录 引言 一.实现逻辑 二.代码实现 2.1 Transition Manager 2.2 Teleport 2.3 Cursor Manager 引言 在unity中可以将不同场景的背景和道具放置在不同的Scene当中,通过对Scene的加载和卸载来实现场景之间的切换.同时创建一个基础场景(Control Scene)来对整个游戏系统进行管理,在基础场景(Control Scene)中不放置背景图片或者游戏道具而只添加各种控制单元和Canvas. 一.实现逻辑 在场景切换的实现过程中需要定义

  • Unity制作游戏自定义按键详解

    目录 一.效果图 二.布局 1.场景布局 2.设置面板布局 三.脚本思路 1.KeyItem脚本 2.SetKeyPanle脚本 3.player移动脚本 一.效果图 二.布局 1.场景布局 创建一个Panel 创建三个cube,Panel地板 两个cube设置一个绿色材质,调整Scale大小让其成为柱子形状,一个cube改名为player设置一个红色材质,当作玩家(用来演示操作的),修改相机位置就可以了. 2.设置面板布局 2.1新建一个空节点名字改为SetKeyPanle,修改属性 2.2在

  • Unity3D实现甜品消消乐游戏

    目录 前言 项目效果展示 项目概况 素材展示 场景展示 场景元素 玩法介绍 版本说明 项目源码 前言 解释: 之前用的ScreenToGif录屏,因为上传的.gif最大不超过5MB,所以做了不少删帧和色彩弱化等处理,这才导致色彩看上去不是很舒服,不要盯着它看太久,不然会有点难受... 由于使用的素材是现成的,没有花时间精力去扒,所以细节方面可能不是做的很好. 说明: 这次的甜品消消乐虽然看上去好像挺简单普通的,但是相对于之前的坦克大战,某种程度上已然提升难度了,归类到了算法类层的游戏. 拉到最后

  • Unity游戏开发之射击小游戏的实现

    目录 前言 游戏画面展示 游戏代码解析 游戏打包 总结 前言 人们一直都说学习和玩游戏不能兼顾,那我们就来边学习怎样制作游戏,边玩游戏 不就兼得了嘛~ 我可真是一个小天才呢~ 所以本篇文章为大家带来一个 横版2D射击小游戏,游戏制作超级简单,玩法一学就会, 一起来看看吧! 游戏画面展示 这款小游戏只用了两个UI界面,一个是菜单界面,另一个是战斗界面 菜单界面有三种模式,分别是一般.困难和地狱 战斗界面就是很简单的从两边刷野怪,然后主角开枪打死他们 UI搭建很简单,只有一张背景图使用Image,加

  • Unity游戏开发实现背包系统的示例详解

    目录 引言 一.UI设计 二.UI 2.1 Slot中的物品显示 2.2 物品切换 2.3 SlotUI的实现 2.4 物品描述信息的展示 三.数据 四.逻辑 引言 背包是游戏中经常使用的一个组件,它负责管理玩家在游戏中所获得的道具.一个完整的背包系统应当具有将物品放置进背包.对背包内物品进行管理和使用背包内物品等功能.而往往一个背包系统的逻辑关系较为复杂,如果把所有功能都放在一个脚本中实现会使代码显得十分冗杂且缺乏逻辑.所以在背包系统的设计过程中,我们常将其分解为数据.逻辑和UI三部分分别来进

  • python编程开发时间序列calendar模块示例详解

    目录 calendar模块 设置每周第一天-setfirstweekday 1.默认情况:礼拜一是第一天 2.设置任意一天 是否闰年-isleap 年份间的闰年数-leapdays(y1, y2) 星期几-weekday(year, month, day) monthrange(year, month) 月的日历矩阵-monthcalendar(year, month) 月的日历-prmonth(year, month, w, l) 年的日历-calendar.calendar(year) 格式

  • IOS开发Objective-C Runtime使用示例详解

    目录 前言 一些关键字 消息传递 (Messaging) KVO 关联对象 (Associated Objects) AOP(Method Swizzling) 其它 前言 Runtime 是使用 C 和汇编实现的运行时代码库,Objective-C 中有很多语言特性都是通过它来实现.了解 Runtime 开发可以帮助我们更灵活的使用 Objective-C 这门语言,我们可以将程序功能推迟到运行时再去决定怎么做,还可以利用 Runtime 来解决项目开发中的一些设计和技术问题,使开发过程更加具

  • golang编程开发使用sort排序示例详解

    golang sort package: https://studygolang.com/articles/3360 sort 操作的对象通常是一个 slice,需要满足三个基本的接口,并且能够使用整数来索引 // A type, typically a collection, that satisfies sort.Interface can be // sorted by the routines in this package. The methods require that the /

  • Lua游戏开发教程之时区问题详解

    前言 什么是Lua? Lua 是一个小巧的脚本语言,巴西里约热内卢天主教大学里的一个研究小组于1993年开发,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能.Lua由标准C编写而成,几乎在所有操作系统和平台上都可以编译,运行.一个完整的Lua解释器不过200k,在目前所有脚本引擎中,Lua的速度是最快的.这一切都决定了Lua是作为嵌入式脚本的最佳选择.相比Python和Per的内核,Lua的内核小于120KB,而Python的内核大约860KB,Perl的内核大约1.1M

  • Python实现过迷宫小游戏示例详解

    目录 前言 开发工具 环境搭建 原理简介 主要代码 前言 今天为大家带来解闷用的过迷宫小游戏分享给大家好了.让我们愉快地开始吧~ 开发工具 Python版本: 3.6.4 相关模块: pygame模块: 以及一些Python自带的模块. 环境搭建 安装Python并添加到环境变量,pip安装需要的相关模块即可. 原理简介 游戏规则: 玩家通过↑↓←→键控制主角行动,使主角从出发点(左上角)绕出迷宫,到达终点(右下角)即为游戏胜利. 逐步实现: 首先,当然是创建迷宫啦,为了方便,这里采用随机生成迷

  • Unity InputFiled TMP属性和各种监听示例详解

    目录 实践过程 Input Field Settings Control Settings InputField(TMP)事件监听 实践过程 Input Field Settings Font Asset:字体文件资源 Point Size:控制的字大小 Character Limit:字符限制,当输入内容超过指定数量,不再接收新输入的内容.通常用户登录页面我们都会限制不要输入太多. Content Type:输入类型(Standard--标准,可以输入任何字符:Auto corrected--

  • Servlet开发JavaWeb工程示例详解

    一.什么是Servlet? Servlet是在服务器上运行的小程序,也就是一个Java类,但比较特殊,不需要new,自动就可以运行.也有创建.垃圾回收和销毁过程.Servlet是JavaWeb的三大组件之一(Servlet.Filter.Listener),它属于动态资源.Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要: 接收请求数据: 处理请求: 完成响应. 例如客户端发出登录请求,或者输出注册请求,这些请求都应该由Servlet来完

  • 基于gin的golang web开发:路由示例详解

    Gin是一个用Golang编写的HTTP网络框架.它的特点是类似于Martini的API,性能更好.在golang web开发领域是一个非常热门的web框架. 启动一个Gin web服务器 使用下面的命令安装Gin go get -u github.com/gin-gonic/gin 在代码里添加依赖 import "github.com/gin-gonic/gin" 快速启动一个Gin服务器的代码如下 package main import "github.com/gin-

随机推荐