unity编辑器xml数据库插件
注:9月9日更新,其中MyXML.cs中有一句代码写错,查找功能失误,文中已经修改!
注:9月1日更新说明:xml存储结构,因为在用xml之前不知道正规的xml数据结构,所以是自创的结构。虽然也能完成功能,但是据说策划配置时不方便,所以为了统一,不使用节点的方式存储数据,
而是通过添加属性,设置属性的方式来存取数据。
直接上图看的清楚些:
我之前设计的格式:
现在的格式:
关于这部分的代码我会贴在最后。
程序和数据分离的意义我就不多说了,大家自己脑补或者百度。在使用unity开发时,数据的调试是非常频繁和重要的。我们可以制作一个简单的编辑器插件,将数据显示在Inspector面板上,并进行编辑操作。这样测试人员就可以非常方便的管理测试数据了。
需求很简单,具体的效果是,能读取资源内的类,将其属性显示在面板上,可以对此进行增删改查的操作。如下图所示(对象组,相当于数据库所有的表。对象,相当于表的所有记录)。
当需要创建一条新记录的时候,先填上主键,然后点击创建按钮。编辑完成后点击插入即可。
xml数据库文件如下图
要实现这个功能,需要的知识是,C#的反射类,unity的编辑器类,数据库。通过反射,自动解析对象,获取对象的成员变量名和值。Unity编辑器类没什么好说的,就是一些组件方法的使用。考虑到跨平台等问题,我选择xml作为存储数据库。编辑器内运行,存储量不大,所以性能方面的问题也就不说了。
好,接下来说一说设计的事。首先是对象的反射。基本类型的存储没有问题,难点是数组的存取有点变态。我找了很多资料也不能自动创建某一类型的数组。既然不能自动,然后就使用半自动判断了,无非是if else之类的,看看这个属性是不是某一类型的数组。
下面是代码。
using System;
using System.Reflection;
using UnityEngine;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public class ClassAnalyze
{
private string[] cols;
public string[] Cols
{
get { return cols; }
set { cols = value; }
}
private string[] values;
public string[] Values
{
get { return values; }
set { values = value; }
}
public string ClazzName
{
get { return tempClazz.GetType().Name; }
}
private PropertyInfo[] property;
private T tempClazz;
public static System.Object CreateObject(string objName) {
return Assembly.GetExecutingAssembly().CreateInstance(objName);
}
public T GetClazz(string[] values)
{//将数值赋给对象,然后再获取
SetClazz(values);
this.Values = values;
if (tempClazz == null)
{
return default(T);
}
return tempClazz;
}
public void SetClazz(string[] values)
{//将数值赋给对象,然后再获取
if (tempClazz != null && this.Values.Length == values.Length)
{
this.Values = values;
for (int i = 0; i < property.Length; i++)
{
if (tempClazz.GetType().GetProperty(Cols[i]).PropertyType.IsArray)
{
var tempArr = StringToArr(tempClazz.GetType().GetProperty(Cols
[i]).GetValue(tempClazz, null), values[i].Split(new char[] { '|' }));
property[i].SetValue(tempClazz, tempArr, null);
}
else
{
property[i].SetValue(tempClazz, Convert.ChangeType(values[i], property[i].PropertyType), null);
}
}
}
}
private System.Object StringToArr(System.Object arr, string[] values)
{
if (arr is string[])
{
arr = new string[values.Length];
for (int i = 0; i < values.Length; i++)
{
(arr as string[])[i] = values[i];
}
return (string[])arr;
}
else if (arr is int[])
{
arr = new int[values.Length];
for (int i = 0; i < values.Length; i++)
{
(arr as int[])[i] = int.Parse(values[i]);
}
return (int[])arr;
}
else if (arr is Single[])
{
arr = new Single[values.Length];
for (int i = 0; i < values.Length; i++)
{
(arr as Single[])[i] = Single.Parse(values[i]);
}
return (Single[])arr;
}
else if (arr is float[])
{
arr = new float[values.Length];
for (int i = 0; i < values.Length; i++)
{
(arr as float[])[i] = float.Parse(values[i]);
}
return (float[])arr;
}
else if (arr is double[])
{
arr = new double[values.Length];
for (int i = 0; i < values.Length; i++)
{
(arr as double[])[i] = double.Parse(values[i]);
}
return (double[])arr;
}
else if (arr is long[])
{
arr = new long[values.Length];
for (int i = 0; i < values.Length; i++)
{
(arr as long[])[i] = long.Parse(values[i]);
}
return (long[])arr;
}
else if (arr is System.Object[])
{
arr = new System.Object[values.Length];
for (int i = 0; i < values.Length; i++)
{