第五章:背包系统
背包系统作为游戏中的一个重要功能,与游戏存在着诸多的交互性,购买商品、怪物掉落等各种情形都需要访问背包系统,结构较为复杂。因此背包系统将通过两篇博客进行分析。
(上)部分包括
- 功能面板创建
- 物品信息管理系统
- 物品栏的UI界面
(下)部分偏向于功能实现,包括
- 拾取操作的模拟
- 背包的显示与隐藏
- 物品提示信息窗口的实现
5.1功能面板
在之前的学习中,还没有功能面板进行创建,因此先创建整体的功能面板。为了实现各种系统,我们需要在UIRoot中创建一个Invisible Wigdet,也就是一个Container,设置其属性如下
添加所有的功能按钮,注意对其方式的左右要向右对齐,这样才能保证分辨率发生变化时图标也能随之自适应变化。
设置完成后如下
为了实现这5个功能按钮的事件监听,我们在Script下建立一个UI文件夹统一处理,新建FunctionBar脚本,存储5个按键功能,在之后的学习中进行完善。将这5个功能函数赋给5个按钮的On Click事件。
public void OnStatusButtonClick() { } public void OnBagButtonClick() { } public void OnEquipButtonClik() { } public void OnSkillButtonClick() { } public void OnSettingButtonClick() { }
在之后的操作中我们会对这些按键功能进行完善。
5.2物品信息管理与外界访问
我们需要通过一个txt文档来储存所有的物品信息,在Assets下(Show in explorer)建立一个文本文档ObjectsInfoInList存储这些信息,如下图所示。
随着功能的完善,物品信息会逐步进行补充,如武器、材料等信息的添加。先以药品为例,txt文档信息的输入如下
1001,smallHpPotion,icon-potion1,Drug,40,0,40,60 //对应血药和蓝药 1002,bigHpPotion,icon-potion2,Drug,80,0,70,100 1003,smallMpPotion,icon-potion3,0,100,70,80
在GameSetting中新建一个脚本ObjectInfo管理物品,随时查找访问信息
using UnityEngine; using System.Collections; public class ObjectsInfo : MonoBehaviour { public static ObjectsInfo _instance; //依旧用单例,方便随时访问 void Awake() { _instance = this; } public enum ObjectType{ //三种用品的枚举 Drug, Equip, Mat } public class ObjectInfo{ //单个物品的信息,可以进一步拆分成多个类,比如hp,mp只属于消耗品,可以单独成类 public int id; public string name; public string icon_name; public ObjectType type; public int hp; public int mp; public int price_sell; public int price_buy; } }
之后需要在程序中对txt中的文本信息进行读取,判断出物品并使用。
在GameSetting中添加一个类
public TextAsset ObjectInfoListText;
用来访问txt信息,将txt文件拖入
在GameSetting中用ReadInfo()读取物品信息,其中信息存储用字典完成
using System.Collections.Generic; private Dictionary<int,ObjectInfo> objectInfoDict = new Dictionary<int, ObjectInfo> (); void ReadInfo(){ string text = ObjectInfoListText.text; //读取ObjectInfoListText中的文本 string[] strArray = text.Split("\n"); //将读取到的文本以“\n”为标识拆分成数组,存储到strArray[]数组中 foreach (string str in strArray) { //将strArray[]数组中的数据以逗号为标识拆分成数组,存储到proArray[]数组中,即把所有txt中的物品信息存入字典 string[] proArray = str.Split(","); ObjectInfo info = new ObjectInfo(); //读取txt中的信息赋值给实例化的info int id = int.Parse(proArray[0]); string name = proArray[1]; string icon_name = proArray[2]; string str_type = proArray[3]; ObjectType type = ObjectType.Drug; switch(str_type){ //根据读到的str_type进行type的设置 case "Drug": type = ObjectType.Drug; break; case "Equip": type = ObjectType.Equip; break; case "Mat": type = ObjectType.Mat; break; } info.id=id;info.name=name;info.icon_name=icon_name; //实例化ObjectInfo类,用以存储各项信息 if(type = ObjectType.Drug) { int hp = int.Parse(proArray[4]); int mp = int.Parse(proArray[5]); int price_sell = int.Parse(proArray[6]); int price_buy = int.Parse(proArray[7]); info.hp=hp;info.mp=mp;info.price_sell=price_sell;info.price_buy=price_buy; //实例化ObjectInfo类,用以存储各项信息 } objectInfoDict.Add(id,info); //数据存入字典中,注意,这里的id作为索引,用于访问对应物品信息,在外界进行访问时需要用到id,因此需要把id与info独立开来! } }
由于字典是private的,如果需要调用信息,可以提供一个接口,即
public ObjectInfo GetObjectInfoFromDict(int id){ ObjectInfo info = null; objectInfoDict.TryGetValue (id, out info); return info; }
即可在外界访问
5.3 背包系统的设计
在UI界面中新建一个Sprite,命名为Inventory,并导入网格,之后加入金币和金币数量(Label)显示。如下
为了在鼠标点击物品栏时角色不移动,对Inventory加入一个box collider即可。
因为背包是经常需要访问的,我们可以设置为单例模式,方便随时进行调用。在Inventory脚本中输入
public static Inventory _instance; private TweenPosition tween; void Awake(){ _instance = this; } public void Show() { tween.PlayForward (); } public void Hide() { tween.PlayReverse (); }
对Inventory脚本添加格子与金币信息等
using System.Collections.Generic; //提供对List的支持 public List<InventoryItemGrid> itemGridList = new List<InventoryItemGrid>(); //用List存储网格信息 private int coinCount = 1000; //金币信息 public UILabel coinNumberLabel; //金币的显示
这些格子与金币信息添加成功后,我们要对每一个格子进行操作,进行物品的添加与使用
首先我们对网格添加一个Script Child作为Prefab,之后导入hp药素材进行初步设置,如下
在网格中要存储物品的外观信息、数量信息以及物品名信息,我们可以在InventoryItemGrid中进行管理。
using UnityEngine; using System.Collections; public class InventoryItemGrid : MonoBehaviour { private int id = 0; //当前网格存储的物品对应id private ObjectsInfo .ObjectInfo info = null; private int num = 0; //当前网格物品个数 private UILabel numberLabel; //显示物品个数的网格 // Use this for initialization void Start () { numberLabel = this.GetComponentsInChildren<UILabel> (); //取自自身子类的UILabel } public void SetId(int id,int num = 1){ //向网格中塞东西,添加物品的数量(number)默认为1 info = ObjectsInfo._instance.GetObjectInfoFromDict (id); //得到字典中的物品信息 InventoryInsideItem item = this.GetComponent<InventoryInsideItem> (); //实例化一个item,用以设置物品显示 item.SetIconName (info.icon_name); //设置item的物品名 numberLabel.gameObject.SetActive (true); //显示numberLabel this.num = num; //形参中的num=1赋值给private int num numberLabel.text = this.num.ToString (); // 给numberLabel赋值 } public void ClearInfo() //当物品进行拖动时,当前网格信息的清空 { id = 0; info = null; num = 0; numberLabel.gameObject.SetActive (false); } }
其中 item.SetIconName (info.icon_name); 是在InventoryInsideItem中的一个函数,实现设置item名称的作用,代码如下
public void SetIconName(string icon_name) { sprite.spriteName = icon_name; }
总结:至此,(上)部分的内容就完成了,主要是一些基础界面和物品信息的创建,(下)部分将介绍背包中的各项功能。