unity编辑器xml数据库插件

unity编辑器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还是很简单的。

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<string[]> 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 CreateDB(string dBName)
    {
        File.CreateText(path).Close();
        XmlDeclaration xmlDeclaration = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
        XmlNode root = xmlDoc.CreateElement(dBName);
        xmlDoc.AppendChild(xmlDeclaration);
        xmlDoc.AppendChild(root);
        xmlDoc.Save(path);
        return root;
    }

    public override bool Insert(string tableName, string[] cols, string[] values,string key)
    {

        if (key == null || key == "") key = values[0];
        key = key.Replace(" ","");
        XmlNode table = CheckTable(tableName);

        XmlNode obj = table.SelectSingleNode(key);//按照key值确定元素对象

        if (obj != null) {//待插入数据已经存在,插入失败
            return false;
        }

        XmlElement element = xmlDoc.CreateElement(key);

        for(int i=0;i<cols.Length;i++){
            XmlElement e = xmlDoc.CreateElement(cols[i]);
            e.InnerText = values[i].Replace(" ", "");
            element.AppendChild(e);
        }
        table.AppendChild(element);
        xmlDoc.Save(path);
        return true;
    }
    public override bool Update(string tableName, string[] cols, string[] values,string key)
    {
        if (key == null || key == "") key = values[0];
        key = key.Replace(" ", "");
        XmlNode table = CheckTable(tableName);

        XmlNode obj = table.SelectSingleNode(key);//按照key值确定元素对象
        if (obj == null)
        {//待更新数据不存在,更新失败
            return false;
        }
        for (int i = 0; i < cols.Length; i++)
        {
            obj.SelectSingleNode(cols[i]).InnerText = values[i].Replace(" ", "");
        }
        xmlDoc.Save(path);
        return true;

    }

    public override bool UpdateAll(string tableName)
    {
        return false;
    }
    public override string[] Select(string tableName, string key)
    {
        XmlNode table = CheckTable(tableName);
        if (key == null || key == "") {
            if (table.ChildNodes.Count < 1) {
            return null;
            }
            key = table.ChildNodes[0].LocalName;
        }
        key = key.Replace(" ", "");

        XmlNode obj = table.SelectSingleNode(key);//按照key值确定元素对象

        if (obj == null) {
            return null;
        }

        string[] values = new string[obj.ChildNodes.Count];

        for (int i = 0; i < values.Length; i++) {
            values[i] = obj.ChildNodes.Item(i).InnerText.Replace(" ", "");
        }

        return values;
    }
    public override string[] SelectAllObjectsName(string tableName)
    {
        XmlNode table = CheckTable(tableName);

        string[] values = new string[table.ChildNodes.Count];

        for (int i = 0; i < values.Length; i++) {
            values[i] = table.ChildNodes[i].LocalName;
        }
        return values;
    }
    public override List<string[]> SelectAll(string tableName)
    {
        XmlNode table = CheckTable(tableName);
        if (table.ChildNodes.Count == 0) {
            return null;
        }
        List<string[]> elements = new List<string[]>();
        for(int i=0;i<table.ChildNodes.Count;i++){

            string[] values = new string[table.ChildNodes[i].ChildNodes.Count];
            for (int j = 0; j < table.ChildNodes[i].ChildNodes.Count; j++) {

                values[j] = table.ChildNodes[i].ChildNodes.Item(j).InnerText.Trim();
            }
            elements.Add(values);
        }
        return elements;
    }
    public override bool Delete(string tableName, string key)
    {
        XmlNode table = CheckTable(tableName);
        if (key == null || key == "") key = table.ChildNodes[0].LocalName;
        key = key.Replace(" ", "");

        XmlNode obj = table.SelectSingleNode(key);//按照key值确定元素对象
        if (obj == null)
            return false;
        obj.RemoveAll();
        table.RemoveChild(obj);
        xmlDoc.Save(path);
        return true;
    }
    public override bool DeleteAll(string tableName)
    {
        XmlNode table = CheckTable(tableName);
        table.RemoveAll();
        xmlDoc.Save(path);
        return true;
    }
}

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

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System;
public class MyInspector : MonoBehaviour {

    //这个类是一个编辑器类,作用是展示存储的xml数据
    //选择对象,然后进行编辑
    //如果数据库中有这个数值,将其读取并显示
    //如果没有,则按需求创建数据
    //public string path;

    public string defaultKey = "PriKey";
    public ObjectMessage objMessage;
    public string DataPath = "gameData.xml";
    public MySql mySql;
    public bool IsHave = false;
    public bool IsShow = false;
    //private System.Object tempObj;
    public void GetDataBase(string dataPath) {
        DB db = MyDataBase.GetDataBase().Connection(dataPath);
        mySql = new MySql(db);
    }

    public void SaveMessage(string objName)
    {
        if (mySql != null)
        {
            System.Object obj = Assembly.GetExecutingAssembly().CreateInstance(objName);
            ClassAnalyze<System.Object> tempAnalyze = new ClassAnalyze<System.Object>(obj);
            obj=tempAnalyze.GetClazz(objMessage.values);

            if (IsHave)
            {
                mySql.Update(obj, defaultKey);

            }
            else {
                mySql.Insert(obj, defaultKey);
                ReadObj(objMessage.NamesOfModel[objMessage.indexOfModel]);
            }

        }
    }
    public void RemoveMessage(string objName, string key)
    {
        if (mySql != null)
        {
            System.Object obj = Assembly.GetExecutingAssembly().CreateInstance(objName);
            ClassAnalyze<System.Object> tempAnalyze = new ClassAnalyze<System.Object>(obj);
            tempAnalyze.SetValue(obj, defaultKey, key);

            if (IsHave)
            {
                mySql.Delete(obj, defaultKey);
                IsHave = false;
                ClearObjMessage();
            }

        }
    }

    public void ClearObjMessage()
    {
        for (int i = 0; i < objMessage.values.Length; i++) {
            objMessage.values[i] = "";
        }
    }

    public void ReadModel() {
        TextAsset[] tas = Resources.LoadAll<TextAsset>(objMessage.objectPath);
        objMessage. NamesOfModel = new string[tas.Length];
        for (int i = 0; i < tas.Length; i++) {
            objMessage.NamesOfModel[i] = tas[i].name;
        }

    }
    public void ReadObj(string tableName)
    {
        if(mySql!=null)
        objMessage.NamesOfObj = mySql.SelectAllObjectsName(tableName);
    }
    public void CheckData(string objName, string key)
    {
        System.Object obj = Assembly.GetExecutingAssembly().CreateInstance(objName);
        ClassAnalyze<System.Object> tempAnalyze = new ClassAnalyze<System.Object>(obj);
        tempAnalyze.SetValue(obj, defaultKey, key);
        objMessage.cols = tempAnalyze.Cols;
        obj = mySql.Select(obj, defaultKey);
        IsHave = (obj != null);
        if (IsHave)
        {
            tempAnalyze = new ClassAnalyze<System.Object>(obj);

            objMessage.values = tempAnalyze.Values;
        }
        else {
            objMessage.values = new string[objMessage.cols.Length];
        }
    }
}
[Serializable]
public class ObjectMessage
{

    public string objectPath = "Model";//对象所处的路径(基于Resources的相对路径)
    public string[] NamesOfModel;
    public string[] NamesOfObj;
    public int indexOfModel = 0;
    public int indexOfObj = 0;
    public string PriKey = "PriKey";
    public string[] cols;
    public string[] values;

}

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

using UnityEngine;
using System.Collections;
using UnityEditor;

[CustomEditor(typeof(MyInspector))]
public class EditorInspector : Editor {
    //重写展示面板

    //用户选择要加载的对象
    //提供一个主键,用户填写主键的值
    //默认主键是游戏对象名称
    //判断此对象是否已经保存在数据库中
    //如果已经存在此主键,则,加载数据到面板
    //如果没有此主键,提示用户是否创建
    //
    private SerializedObject TargetObj;
    private MyInspector MyPlane;
    private string[] shows= new string[]{"创建","加载"};
    private void InitPlane() {
        TargetObj = new SerializedObject(target);//获取编辑对象目标
        MyPlane = target as MyInspector;//转化为编辑对象
        CheckData();//检测数据
    }

    private void CheckData() {
        if (MyPlane.objMessage == null)//检查信息对象是否为空
        {
            MyPlane.objMessage = new ObjectMessage();//对象信息
        }
        if (MyPlane.objMessage.NamesOfModel == null || MyPlane.objMessage.NamesOfModel.Length < 1)
        {//检查对象数组
            MyPlane.ReadModel();//读取对象
        }
        if (MyPlane.objMessage.NamesOfObj == null || MyPlane.objMessage.NamesOfObj.Length < 1)
        {//检查对象数组
            MyPlane.ReadObj(MyPlane.objMessage.NamesOfModel[MyPlane.objMessage.indexOfModel]);//读取对象
        }
        if (MyPlane.objMessage.PriKey == null || MyPlane.objMessage.PriKey == "")
        {//检查对象主键名称
            //设置主键信息
            MyPlane.objMessage.PriKey = MyPlane.gameObject.name.Replace(" ", "");
        }
        if (MyPlane.mySql == null)
        {//检查数据库的连接状态
            //获取数据库连接
             MyPlane.GetDataBase(MyPlane.DataPath);
        }

    }
    void OnEnable() {

        InitPlane();

    }

    public override void OnInspectorGUI()
    {

        TargetObj.Update();//更新目标数据

        //主键值
        //CheckData();
        int lastModel = MyPlane.objMessage.indexOfModel;
        //对象选择列表
        MyPlane.objMessage.indexOfModel = EditorGUILayout.Popup("对象组", MyPlane.objMessage.indexOfModel, MyPlane.objMessage.NamesOfModel);

        if (lastModel != MyPlane.objMessage.indexOfModel) { //当改变对象时,更新主键值
            //更新主键值集合
            MyPlane.ReadObj(MyPlane.objMessage.NamesOfModel[MyPlane.objMessage.indexOfModel]);

        }
        int lastobj = MyPlane.objMessage.indexOfObj;
        if (MyPlane.objMessage.NamesOfObj.Length > 0)
        {
            MyPlane.objMessage.indexOfObj = EditorGUILayout.Popup("对象", MyPlane.objMessage.indexOfObj, MyPlane.objMessage.NamesOfObj);
        }
        if (lastobj != MyPlane.objMessage.indexOfObj || lastModel != MyPlane.objMessage.indexOfModel)
        { //主键值集合下标改变时
            //更新主键值
            if (MyPlane.objMessage.NamesOfObj.Length>0)
            MyPlane.objMessage.PriKey = MyPlane.objMessage.NamesOfObj[MyPlane.objMessage.indexOfObj];
        }

        string lastKey = MyPlane.objMessage.PriKey;
        //显示主键文本框
        MyPlane.objMessage.PriKey = EditorGUILayout.TextField("主键", MyPlane.objMessage.PriKey);
        //路径

        string lastPath = MyPlane.DataPath;
        MyPlane.DataPath = EditorGUILayout.TextField("数据路径",MyPlane.DataPath);

        //判断选择的对象列表
        //更新对象信息

        if (MyPlane.objMessage.indexOfModel != lastModel || lastKey != MyPlane.objMessage.PriKey || lastPath != MyPlane.DataPath || lastobj != MyPlane.objMessage.indexOfObj)//改变了一些数据时重新读取数据
        {
            MyPlane.IsHave = false;//标注数据改动

            CheckData();//读取数据前保证系统参数无误,以及各个对象正确加载

            MyPlane.CheckData(MyPlane.objMessage.NamesOfModel[MyPlane.objMessage.indexOfModel], MyPlane.objMessage.PriKey);
        }

        //当存在时直接加载
        //当不存在时,点击创建时加载

        bool _show = MyPlane.IsShow;//记录上一次的状态
        if (MyPlane.IsHave || (MyPlane.IsShow = EditorGUILayout.Foldout(MyPlane.IsShow, shows[MyPlane.IsShow ? 1 : 0])))
        {
            if (!_show && !MyPlane.IsHave)//数据不存在而且点击了创建的时候
            { //仅执行一次,保证数据不被一直刷新而导致的无法读写
                //当数据不存在,而且点击创建时  清除信息

                MyPlane.ClearObjMessage();//清除数据的缓存
            }
        }
        //也要只进行一次的读写,保证可以进行修改操作
        if (MyPlane.IsHave || MyPlane.IsShow)//当数据存在或者点击创建时加载数据
        {
            for (int i = 0; i < MyPlane.objMessage.cols.Length; i++)
            {
                if (MyPlane.defaultKey == MyPlane.objMessage.cols[i]) {
                    MyPlane.objMessage.values[i] = MyPlane.objMessage.PriKey;
                    continue;
                }
                MyPlane.objMessage.values[i] = EditorGUILayout.TextField(MyPlane.objMessage.cols[i], MyPlane.objMessage.values[i]);

            }
            if (GUILayout.Button("Save"))
            {
                MyPlane.SaveMessage(MyPlane.objMessage.NamesOfModel[MyPlane.objMessage.indexOfModel]);
            }

            if (MyPlane.IsHave&& GUILayout.Button("Remove"))
            {
                MyPlane.RemoveMessage(MyPlane.objMessage.NamesOfModel[MyPlane.objMessage.indexOfModel], MyPlane.objMessage.PriKey);
                MyPlane.ReadObj(MyPlane.objMessage.NamesOfModel[MyPlane.objMessage.indexOfModel]);

            }
        }

        TargetObj.ApplyModifiedProperties();

    }

    void show(System.Object message) {
        Debug.Log(message);
    }
}

部分源码如上。省去了一些源码和路径加载等东西。如果想要完整版,可以联系我。

本文地址:http://www.cnblogs.com/jqg-aliang/p/4767026.html

时间: 2024-10-12 21:49:14

unity编辑器xml数据库插件的相关文章

unity编辑器和插件的制作(四.1)

好久没有更新,有些急事终于处理完了,接着更新博客! 废话不多说,接着上面的讲,今天我们来接着讲述. 前面说到 怎么去建立一个自己 ,用代码绘制一个色块,今天我们来讲述下,怎么绘制一个图片在场景里面. 首先 我们先做下图片的功课. 在unity中图片的种类分了很多,默认是:Texture, 还有其他的一些属性. 有些人可以会遇到 我放进去的素材为什么编译之后会变模糊那,这是由于,在unity中你没有修改图片的属性,导致的. 在 texture模式下, 我们来分析下这种图片的属性, wrap mod

unity 编辑器和插件制作(五)

接着前面的继续前行,默默的fighting. 前面讲了,怎么使用摄像机发射线到物体,来触发事件.今天我们 来讲述下怎么去实现一个label. 这个就相对比较简单了,其实我们可以直接使用unity自带得textmesh来实现一个字体,但大多数时候,需要改一些设置,字体大小,材质等等 一些得问题所以我们,最好还是自己写一个脚本来实现一些简单的操作,方便简洁嘛.其实很简单 ,下面我们就开始来实现这些方法. 代码 : using UnityEngine; using System.Collections

unity编辑器和插件(三)

接下来 我就开始正规的编辑器和插件的制作. 我这里是按照 IOS android的 控件为例子模板.来制作 一套使用 unity书写的控件. 好首先我们来想下  IOS 和android的 控件都是以四边形基础的. SO, 接下来 我们来转像unity,在unity中 我们怎么去建立一个四边形那, 依照图形绘制的原理.三点一面的理论.我们可以使用6个点来建立一个两三角形组成的四边形. 我们先学会怎么去绘制一个view,也就是简单的一个色面. 我们知道 unity中得面也是采取这种的绘制方法,绘制

unity 编辑器和插件制作(四.2)

上次 我们讲述的是编辑器制作,怎么把图片加载到场景中,今天 我们就来讲述下,怎么 制作UIButton以及UIimage的互换. 废话不多说.进入正题. 首先我们要了解 unity的机制,button属性必须有的属性等. 首先 我们先说下 unity的机制: unity中检测点击事件,使用NGUI的可能知道,NGUI使用的就是SendMessage的方式来进行事件的传递.没错,这也是 unity最为简便的方式, (要注意一个问题哦,这个方式 如果 你要使用 大于 万次循环的话 会有延迟的哦,一般

Unity编辑器扩展chapter1

Unity编辑器扩展chapter1 unity通过提供EditorScript API 的方式为我们提供了方便强大的编辑器扩展途径.学好这一部分可以使我们学会编写一些工具来提高效率,甚至可以自制一些小的插件应用的项目工程中去,达到复用的目的.今天首先创建一个新场景生成的菜单项,生成的场景已经绑定好需要的游戏对象及脚本. Tips:1.官方API 2.编辑器扩展脚本都需放在Editor文件夹下,Editor的层级和数目没有要求 EditorUtil.cs :编辑器扩展类,向外部提供编辑器扩展方法

unity中使用FingerGestures插件3.0

FingerGestures是一个unity3D插件,用来处理用户动作,手势. 译自FingerGestures官方文档 目录 FingerGestures包结构 FingerGestures例子列表 设置场景 教程:识别一个轻敲手势 教程:手势识别器 教程:轻击手势识别器 教程:拖拽手势识别器 教程:滑动手势识别器 教程:长按手势识别器 教程:缩放手势识别器 教程:旋转手势识别器 教程:自定义手势识别器 教程:识别手势事件 建议:使用.net代理事件 fingerGestures包结构 路径,

Android Studio如何导出可供Unity使用的aar插件详解 转

Android Studio如何导出可供Unity使用的aar插件详解 前言 项目之前使用Eclipse导出的jar文件来做与Android交互,最近因为工作需要需使用Android Studio的aar文件,网上参考了部分文章,也结合自己的理解重新整理一下具体的方法,通过写一个测试Demo来表述Android Studio创建aar的过程与及Unity如何使用aar文件,希望对刚好有这个需求的人能起到部分帮助与引导,同时如果文中有误希望也能不吝赐教. 版本信息 Unity 5.3.1f1, A

一个C#的XML数据库访问类

原文地址:http://hankjin.blog.163.com/blog/static/33731937200942915452244/ 程序中不可避免的要用到配置文件或数据,对于数据量比较小的程序,部署数据库花费的时间就显得浪费了,因此用XML来存储不妨为一个很好的办法,而且结合C#的DataSet,我们可以很轻易的封装出一个代码简单而功能强大的数据访问类XMLConfigconfig.xml<root>  <table1>    <rowName1>hello&l

Unity编辑器生成可配置编辑文件

using UnityEditor; public class PoolManagerEditor { [MenuItem("Manager/Creat GameObjectPoolConfig")] static void CreatGameObjectPoolList() { GameObjectPoolList poolList = ScriptableObject.CreateInstance<GameObjectPoolList>();//生成可编辑对象 stri