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

一、UI设计


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

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

二、UI

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

//InventoryUI.cspublic 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.csprivate 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.cspublic Text itemNameText;

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

//ItemToolTip.cspublic 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.cspublic List<ItemDetails> itemDetailsList = new List<ItemDetails>();public ItemDetails GetItemDetails(ItemName itemName){return itemDetailsList.Find(i => i.itemName.Equals(itemName));}

四、逻辑

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

//Item.cspublic 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);}/// <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游戏开发:背包系统的实现相关推荐

  1. 总结下花了大约半年的时间从零开始的unity游戏开发(1)

    从那个2016年8月份左右 ,受了自己爱好的影响,入坑了Unity游戏开发的路上了.知道现在2017年3月20号,我在一家手游公司呆了4个月了,其中加班的日子总是星期一到星期六,每天早上9点上到晚上1 ...

  2. Unity游戏开发大师班

    大小解压后:8.63G 持续时间19h 包含项目文件 1280X720 MP4 语言:英语+中英文字幕(根据原英文字幕机译更准确) Unity游戏开发大师班 信息: 要求 –没有课程要求,展示了开发过 ...

  3. 最全面的Unity游戏开发指南视频教程 第2卷

    最全面的Unity游戏开发指南视频教程 第2卷 流派:电子学习| MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz 语言:英语+中英文字幕(根据原英文字幕机译更准确)|大小 ...

  4. Unity 游戏开发技巧集锦之使用cookie类型的纹理模拟云层的移动

    Unity 游戏开发技巧集锦之使用cookie类型的纹理模拟云层的移动 使用cookie类型的纹理模拟云层的移动 现实生活中,当阳光直射大地,而天空中又有很多云时,云层的影子总是会投射在大地上,风吹着 ...

  5. Unity 游戏开发技巧集锦之创建透明的材质

    Unity 游戏开发技巧集锦之创建透明的材质 Unity创建透明的材质 生活中不乏透明或者半透明的事物.例如,擦的十分干净的玻璃,看起来就是透明的:一些塑料卡片,看起来就是半透明的,如图3-23所示. ...

  6. Unity 游戏开发技巧集锦之创建部分光滑部分粗糙的材质

    Unity 游戏开发技巧集锦之创建部分光滑部分粗糙的材质 创建部分光滑部分粗糙的材质 生活中,有类物体的表面既有光滑的部分,又有粗糙的部分,例如丽江的石板路,如图3-17所示,石板的表面本来是粗糙的, ...

  7. Unity 游戏开发技巧集锦之创建自发光材质

    Unity 游戏开发技巧集锦之创建自发光材质 创建自发光材质 自发光材质(self-illuminated material)是指自己会发光的材质.生活中与之相似的例子,就是液晶显示屏上显示的信息,文 ...

  8. ​Unity 游戏开发技巧集锦之制作一个望远镜与查看器摄像机

    ​Unity 游戏开发技巧集锦之制作一个望远镜与查看器摄像机 Unity中制作一个望远镜 本节制作的望远镜,在鼠标左键按下时,看到的视图会变大:当不再按下的时候,会慢慢缩小成原来的视图.游戏中时常出现 ...

  9. Unity游戏开发技巧集锦2.1.3实现效果

    Unity游戏开发技巧集锦2.1.3实现效果 将此脚本加到Camera对象上,选中此对象,即可查看对象上此脚本组件中的各项属性,如图2-4所示. 图2-4  对象脚本组件里的各项属性          ...

  10. 删除 jar 的 asset_【unity游戏开发】SDK学习(1)-C#与jar交互

    引言 通常一款游戏开发到后期,一般都会涉及到第三方SDK的接入与集成 对于不熟悉SDK接入的同学来说,接SDK每次都是云里雾里, 而熟悉SDK接入的同学又觉得不断地重复做接入SDK工作这样没有成就感, ...

最新文章

  1. 如何在空硬盘Linux系统,Linux系统如何新增一块硬盘
  2. 70 周岁快乐 | 盛世华诞,每一刻都值得铭记
  3. ecms 列表模板php,帝国CMS列表页模板list.var分别调用年月日(显示个性时间日期)
  4. Struts2.x教程(一) Struts2介绍
  5. SAP 是不是很烂的一个ERP软件
  6. 查缺补漏知识点(一)
  7. 让数据分析更easy的选择—贪心科技AI商业数据分析课程深度测评
  8. java-word模板导出
  9. 同一台计算机同时安装多个打印机,r230驱动-同一台电脑可不可以装两台同品牌同型号的打印 – 手机爱问...
  10. ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  11. 实时vad(替换webrtcvad)
  12. 怎样用python删除excel中的_Python+Xlwings 删除Excel的行和列
  13. [半监督学习] Combining Labeled and Unlabeled Data with Co-Training
  14. 敲一万小时的代码可以成为大牛吗?
  15. r2_score与accuracy_score的区别
  16. css介绍css选择器
  17. PMI-ACP练习题(13)
  18. java 接口 抛出异常_Java接口抛出异常,但接口实现不抛出异常?
  19. 腾讯视频自动签到详细版(多种方式得V值)
  20. 2020-10-26

热门文章

  1. 8款逆天的在线实用工具
  2. 如何查html病毒svchost.exe,网站快照劫持又一例:svchost.exe病毒快照劫持的解决办法...
  3. 二次型特征值的猜根法应用
  4. 某天是星期几 + 三目运算符的一些错误操作解释
  5. 简单整理一下以英文字母命名或者开头的语言
  6. blos硬盘启动台式计算机,戴尔台式机bios设置硬盘启动教程--系统之家
  7. 大学计算机信息技术课程评价,信息技术课程学习心得体会精选范文
  8. 向上的箭头 html,HTML中利用div+CSS实现简单的箭头图标
  9. 改变世界的webp图片技术,节约你的流量和带宽
  10. MySQL事务的保证机制