unity3d制作背包系统(4)--数据读取类

unity3d制作背包系统(4)–数据读取类

一般游戏中的物品少则数十种,多则上千上万,这么多的物品肯定是不能自己手动在编辑器中赋值完成的,因此需要从文件中读取物品数据。

关于xml的简单介绍

关于xelement的文档

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

背包系统的其他笔记

整体结构
上一篇:存储部分

文章正在完善中,如有错误或不合理的地方还请谅解

猜你喜欢

转载自blog.csdn.net/ardepomy/article/details/89005240
今日推荐