unity编辑器xml数据库插件
注:9月9日更新,其中MyXML.cs中有一句代码写错,查找功能失误,文中已经修改!
注:9月1日更新说明:xml存储结构,因为在用xml之前不知道正规的xml数据结构,所以是自创的结构。虽然也能完成功能,但是据说策划配置时不方便,所以为了统一,不使用节点的方式存储数据,
而是通过添加属性,设置属性的方式来存取数据。
直接上图看的清楚些:
我之前设计的格式:
现在的格式:
关于这部分的代码我会贴在最后。
程序和数据分离的意义我就不多说了,大家自己脑补或者百度。在使用unity开发时,数据的调试是非常频繁和重要的。我们可以制作一个简单的编辑器插件,将数据显示在Inspector面板上,并进行编辑操作。这样测试人员就可以非常方便的管理测试数据了。
需求很简单,具体的效果是,能读取资源内的类,将其属性显示在面板上,可以对此进行增删改查的操作。如下图所示(对象组,相当于数据库所有的表。对象,相当于表的所有记录)。
当需要创建一条新记录的时候,先填上主键,然后点击创建按钮。编辑完成后点击插入即可。
xml数据库文件如下图
要实现这个功能,需要的知识是,C#的反射类,unity的编辑器类,数据库。通过反射,自动解析对象,获取对象的成员变量名和值。Unity编辑器类没什么好说的,就是一些组件方法的使用。考虑到跨平台等问题,我选择xml作为存储数据库。编辑器内运行,存储量不大,所以性能方面的问题也就不说了。
好,接下来说一说设计的事。首先是对象的反射。基本类型的存储没有问题,难点是数组的存取有点变态。我找了很多资料也不能自动创建某一类型的数组。既然不能自动,然后就使用半自动判断了,无非是if else之类的,看看这个属性是不是某一类型的数组。
下面是代码。
反射搞定后就是设计xml数据库了,具体的功能看个人需求。关于操作xml还是很简单的。
using System.Xml;
using System.Collections.Generic;
using System.IO;
using System;
using UnityEngine;
public abstract class DB
{
/*public abstract bool CheckTable(string tableName);
public abstract bool CheckDB(string dBName);
public abstract void CreateTable(string tableName);
public abstract void CreateDB(string dBName);*/
public abstract bool Insert(string tableName, string[] cols, string[] values, string key);
public abstract bool Update(string tableName, string[] cols, string[] values, string key);
public abstract bool UpdateAll(string tableName);
public abstract bool Delete(string tableName, string key);
public abstract bool DeleteAll(string tableName);
public abstract string[] Select(string tableName, string key);
public abstract List SelectAll(string tableName);
public abstract void Connect(string path);
public abstract void Close();
public abstract string[] SelectAllObjectsName(string tableName);
}
public class XmlSql : DB
{
//public static string values[0] = "values[0]";
private XmlDocument xmlDoc;
private string path;
private string rootName;
public XmlSql()
{
xmlDoc = new XmlDocument();
}
public XmlSql(string path)
{
xmlDoc = new XmlDocument();
Connect(path);
}
public override void Connect(string path)
{
if (xmlDoc == null) xmlDoc = new XmlDocument();
if (!CheckDB(path))
{
this.path = path;
rootName = path.Substring(path.LastIndexOf("/")+1,path.LastIndexOf(".")- path.LastIndexOf("/")-1);
CreateDB(rootName);
}
else {
this.path = path;
xmlDoc.Load(this.path);
rootName = xmlDoc.LastChild.LocalName;
}
}
public override void Close()
{
if (xmlDoc != null)
xmlDoc.Save(path);
GC.Collect();
}
public XmlNode CheckTable(string tableName)
{
XmlNode root = xmlDoc.SelectSingleNode(rootName);
if (root.SelectSingleNode(tableName) != null) {
return root.SelectSingleNode(tableName);
}
return CreateTable(root,tableName);
}
public bool CheckDB(string dBName)
{
return File.Exists(dBName);
}
public XmlNode CreateTable(XmlNode root,string tableName)
{
XmlNode table = xmlDoc.CreateElement(tableName);
root.AppendChild(table);
xmlDoc.Save(path);
return table;
}
public XmlNode