unity3d制作背包系统(4)–数据读取类
一般游戏中的物品少则数十种,多则上千上万,这么多的物品肯定是不能自己手动在编辑器中赋值完成的,因此需要从文件中读取物品数据。
关于xml的简单介绍
0.序言
下文的idtoitem,idtotexture,autogetdata可以随便放场景中的任何游戏中不会被销毁的gameObject上,最好都放在同一个gameObject上
注:物品的数据文件被放在Asset/data/item/下的items.xml中
物品的图片放在Asset/Resources/texture/item/目录下
一些准备工作
为了不再解析物品的脚本里引入读取文件的代码,以及方便所有需要读取xml文件的脚本,编写了autogetdata
autogetdata负责读取数据
using UnityEngine;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Linq;
public class autogetdata : MonoBehaviour {
public static XElement readxml(string path, bool encypt = false)
{//encypt为是否加密,这里没有使用,可以自行加入xml加密代码
FileInfo f = new FileInfo(path);
if (f.Exists)
{
XElement temp = XElement.Load(path);
if (temp != null)
Debug.Log("读取成功" + path);
//List<XElement> t = temp.Element("root").Elements("craft") as List<XElement>;
return temp;
}
else { Debug.Log("无此文件" + path); return null; }
}
public static XElement getdataxml(string name)
{
switch (name)
{
case "items":
return readxml(Application.dataPath + "/data/items/items.xml");
break;
default: return null;
break;
}
}
}
物品的xml格式
使用xml的形式对数据进行存储,单个物品的xml格式为
<item nam="物品名" id="1" sub="0" img="card1-1" max="1">
<exd />
</item>
其中
- nam是物品名称
- id是物品id
- sub对应subid
- img代表该物品对应的显示图片
- max代表该物品最大堆叠数
为了简洁,物品描述之类的就不加入物品的xml中了,如果想加入更多的数据可以修改idtoitemunit中的xml解析部分以及xml本身
1.解析物品数据
idtoitemunit负责
1.解析数据
2.将xml转化为itemunit实例
3.提供根据物品id获取物品实例的静态公用delegate
首先引入的命名空间
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Linq;
定义delegate
public delegate itemunit getitem(int id, int subid);
public delegate int getmaxnum(int id);
public delegate List<itemunit> getitemall(int id);//id象征类型
[RequireComponent(typeof(idtotexture))]
public class idtoitemunit : MonoBehaviour
{
public static getitem idtoitem;//失败返回null
public static getmaxnum idtomaxnum;
public static getitemall idtoitemall;//失败返回null
public Dictionary<long, itemunit> itemdict = new Dictionary<long, itemunit>();//建立id与物品实例的对应关系
void Awake () {
itemunit.nullitem = new itemunit();
loaditems();//完成加载物品数据的入口
idtoitem = new getitem(getite);
idtomaxnum = new getmaxnum(getmax);
idtoitemall = new getitemall(getallitem);
}
public int getmax(int id)
{
itemunit ite;
itemdict.TryGetValue(id, out ite);
return ite.maxnum;
}
即将被注册到静态delegate中的 根据id返回物品实例的方法(itemunit)
public itemunit getite(int id, int subid)
{
itemunit ite;
itemdict.TryGetValue(id, out ite);
itemunit retite = new itemunit();
if (ite == null)
{
Debug.Log("没有此ID物品" + id + " " + subid);
return retite;
}
else
{
retite.copyinfo(ite);
retite.subid = subid;
return retite;
}
Debug.Log("没有此ID物品");
return new itemunit();
}
因为不想在idtotexture里再读取一次物品数据,所以当读取到物品的img字段后调用此方法通知idtotexture该id对应的图片名称
idtotexture cache;
void setdat(int id,int subid,string dis)//设置id与图片对应
{
if(cache==null)
cache = gameObject.GetComponent<idtotexture>();
cache.setdata(id,subid, dis);
}
下面这个方法的功能是“获取全部物品实例”,是给创造模式背包调用的
public List<itemunit> getallitem(int id)//作弊调用的拿取全部物品
{
List<itemunit> allitem = new List<itemunit>();
switch(id)
{
case 0:
foreach(KeyValuePair<long ,itemunit> kpi in itemdict)
{
allitem.Add(kpi.Value);
}
break;
default:
break;
}
return allitem;
}
将解析物品数据的过程分为两个方法
void loaditems()//加载所有物品数据,分为一个个单独的物品数据
{
XElement temp = autogetdata.getdataxml("items");//读取物品数据文件
List<XElement> allgun = new List<XElement>(temp.Elements());
for (int i = 0; i < allgun.Count; i++)
{
itemunit newitemubit = xmltoitem(allgun[i]);
newitemubit.num = 1;
//Debug.Log("新增item:" + newitemubit.id + " " + newitemubit.subid);
if(!itemdict.ContainsKey(newitemubit.id))
itemdict.Add(newitemubit.id, newitemubit);
}
}
itemunit xmltoitem(XElement item)//解析单个物品
{
itemunit item = new itemunit();
item.id = int.Parse(item.Attribute("id").Value);
item.name = item.Attribute("nam").Value;
item.subid = int.Parse(item.Attribute("sub").Value);
item.maxnum = int.Parse(item.Attribute("max").Value);
setdat(item.id, item.subid, "item/" + item.Attribute("img").Value);//通知idtotexture该物品的图片名称
return item;
}
}
2.建立图片与物品对应关系
idtotexture负责建立id和图片间的对应关系,对外界提供根据物品实例获取显示用图片的静态公用delegate
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public delegate Texture totexture(itemunit item);
public class idtotexture : MonoBehaviour {
public static totexture itemtotexture;
public Texture itemtext,nulltexture;//物品无材质时的默认图片
public Dictionary<long, Texture> itemlist = new Dictionary<long, Texture>();
//id与图片的对应关系是由字典来实现的
long itemoffset = 10000;
int nonullnum = 0;
void Awake () {
itemtotexture = new totexture(totext);
// Debug.Log("texture now have" + gunlist.Count);
}
该方法将被注册给静态delegate“itemtotexture”以实现‘根据物品实例获取显示用图片’功能
public Texture totext(itemunit item)
{
if (item.num > 0)//仅处理非空物品
{
int temp = item.id / idtoitemunit.itemoffset;
//Debug.Log("请求者为" + item.id);
switch (temp)//0,normal 1,weapon 2,tool 3,bulet
{
case 0:
Texture tempitem;
itemlist.TryGetValue(item.id*itemoffset+item.subid, out tempitem);
if (tempitem != null) return tempitem;
else
{
//Debug.Log(item.id + "无材质");
if (item.id != 0)
return nulltexture;
}
return itemtext;
break;
default:
return itemtext;
break;
}
}
else return itemtext;//无对应图片则返回默认图片
}
string textpath = "texture/";
public void setdata(int id,int subid,string text)//读取xml数据时被idtoitemunit调用
{
Texture addtext=itemtext;
addtext =Resources.Load(textpath + text)as Texture;
int type = id / idtoitemunit.itemoffset;
switch (type)
{
case 0:
if (addtext != null)
{
//Debug.Log("添加材质成功" + id + textpath + text);
itemlist.Add(id * itemoffset + subid, addtext);
}
break;
default:
break;
}
}
}
一些遗漏
上一章使用到的numtexthandler还并未有代码实现,只是描述了它的功能是根据传入的itemunit设置对应的图片到格子上的rawImage上以及显示数量
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class numtexthandler : MonoBehaviour {
Text tex;
RawImage pict;
void Awake()
{
tex = transform.GetChild(0).GetComponent<Text>();
pict = gameObject.GetComponent<RawImage>();
}
public void inits()
{
tex = transform.GetChild(0).GetComponent<Text>();
pict = gameObject.GetComponent<RawImage>();
}
public void setpicture(itemunit item)
{
pict.texture= idtotexture.itemtotexture(item);
if (item.num>1)
tex.text = item.num.ToString();
else tex.text = "";
}
}
背包系统的其他笔记
demo
地址
提取码:o7y1
个人水平有限,如有错误或不合理的地方欢迎建议