Unity教程之-unity3d编辑器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<T>
{
    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++)
            {
                (arr as System.Object[])[i] = values[i];
            }
            return (System.Object[])arr;
        }
        return arr;
    }
    private string ArrToString(System.Object arr)
    {
        string values = "";
        if (arr is System.Object[])
        {
            foreach (var value in arr as System.Object[])
            {
                values += value + "|";
            }
        }
        else if (arr is string[])
        {
            foreach (var value in arr as string[])
            {
                values += value + "|";
            }
        }
        else if (arr is int[])
        {
            foreach (var value in arr as int[])
            {
                values += value + "|";
            }
        }
        else if (arr is Single[])
        {
            foreach (var value in arr as Single[])
            {
                values += value + "|";
            }
        }
        else if (arr is float[])
        {
            foreach (var value in arr as float[])
            {
                values += value + "|";
            }
        }
        else if (arr is double[])
        {
            foreach (var value in arr as double[])
            {
                values += value + "|";
            }
        }
        else if (arr is long[])
        {
            foreach (var value in arr as long[])
            {
                values += value + "|";
            }
        }
        values = values.TrimEnd(new char[] { '|' });
        return values;
    }
    public void AnalyzeClazz()
    {
        if (tempClazz != null)
        {
            property = tempClazz.GetType().GetProperties();
            Cols = new string[property.Length];
            Values = new string[property.Length];
            for (int i = 0; i < property.Length; i++)
            {
                Cols[i] = property[i].Name;
                string value = "";
                if (tempClazz.GetType().GetProperty(Cols[i]).PropertyType.IsArray)
                {
                    value = ArrToString(tempClazz.GetType().GetProperty(Cols[i]).GetValue(tempClazz, null));
                }
                else
                {
                    value = Convert.ToString(tempClazz.GetType().GetProperty(Cols[i]).GetValue(tempClazz, null));
                }
                Values[i] = value;
            }
        }
    }
    private ClassAnalyze()
    {
    }
    public ClassAnalyze(T tempClazz)
    {
        this.tempClazz = tempClazz;
        AnalyzeClazz();
    }
    public void Close()
    {
        tempClazz = default(T);
        Cols = null;
        Values = null;
        property = null;
    }
    public System.Object GetValue(T t, string colName)
    {
        return tempClazz.GetType().GetProperty(colName).GetValue(tempClazz, null);
    }
    public void SetValue(T t, string colName,string value)
    {
        for (int i = 0; i < property.Length; i++) {
            if (property[i].Name == colName) {
                if (property[i].PropertyType.IsArray)
                {
                    var tempArr = StringToArr(property[i].GetValue(tempClazz, null), value.Split(new char[] { '|' }));
                    property[i].SetValue(tempClazz, tempArr, null);
                }
                else {
                    property[i].SetValue(tempClazz, Convert.ChangeType(value, property[i].PropertyType), null);
                
                }
                break;
            }
        }
    }
    public override string ToString()
    {
        string values = "";
        for (int i = 0; i < Cols.Length; i++)
        {
            values += Cols[i] + ":{" + this.Values[i] + "} ";
        }
        return base.ToString() + ": " + values;
    }
}

 

反射搞定后就是设计xml数据库了,具体的功能看个人需求。关于操作xml还是很简单的。

复制代码

复制代码

 

接下来就是编辑器的设计。没什么高大上的东西,就是一些读写和调用的方法,以及一些逻辑上的处理。

复制代码

复制代码

下面这个脚本要放在Editor目录下面

复制代码

好了,本篇unity3d教程到此结束,下篇我们再会!