利用EditorWindow配製序列化數據表格

簡介:

程序開發中需要連接網絡或在程序外部進行配製的數據,一般不保存在unity自身序列化的文件中。但一些固定的數據類型,利用unity3d自身的序列化功能,配合Editor編程可以方便快速的製作可擴展的數據加載模塊,需要更換數據源也變得十分便利。本文就一個比較複雜的可序列化類,利用Editor窗口編程,實現數據的快速配製。

一、數據模型

1、準備一個數據類DataItem,需要爲類添加Serializable屬性,這樣可以利用unity3d的序列化功能記錄到文件中
[Serializable]
public class DataItem
{
    public string name;
    public List<float> values;
    public string unitName;

    #region graph
    public bool graph = true;
    public string graphName;
    public float axisMin;
    public float axisMax;
    public float axisSize;
    #endregion
}

2、還是使用一個更加複雜的類,上面的一個類直接在面版上進行編輯就好了,沒有必要使用EditorWindow到重新寫一遍顯示(其實也是因爲實際項目用到這樣一個複雜的類,順便不用重新寫一個新的)

[Serializable]
public class DataList
{
    public string name;
    public DataItem key;
    public List<DataItem> values;
}

3、寫一個可序列化的對象,並且添加創建菜單(同時這個對象創建出來後在Inspactor面版上所顯示的數據變得異常複雜)
[CreateAssetMenu(fileName = "LoadForceDataObject.asset", menuName = "生成/加載數據")]
public class LoadForceDataObject : ScriptableObject {
    public List<DataList> dataList;
}
4、在Inspactor面版上的顯示效果如下,顯然在這樣的面版中進行數據配製十分困難(還只設置了一個DataList和其中一個Key,,,)

二、設計人性化的配製面版

1、分析數據類型

     在窗口界面中應該有一個放置數據源的輸入框,在有數據的情況下可以顯示一個大的可縮放的可視化區域,這其中每一個DataList對象顯示爲一個小的固定大小的區域,在其中至少有一個固定的DataItem作爲Key,DataItem中其中的Values不想一個一個填寫,要求可以進行對一個串以符號分割的字符串進行split,自動加載到其中去。

2、繪製草圖

    按以上的思路進行設計,可以做出以下的草圖

三、實現細節

1、建立窗口類,並實現窗口打開。按如下腳本可以實現一個editor模式下的指定大小的小窗口
public class DataTableWindow : EditorWindow
{

    [MenuItem("Window/DataTable")]
    static void CreateWindow()
    {
        EditorWindow window = EditorWindow.GetWindow<DataTableWindow>("數據配製", true);
        window.position = new Rect(200, 300, 600, 400);
        window.maxSize = new Vector2(600, 400);
    }
}

2、繪製數據源,實現效果如下圖所示

  void DrawHead()
    {
        using (var scope = new EditorGUILayout.HorizontalScope())
        {
            GUI.Box(scope.rect, new GUIContent());
            EditorGUILayout.SelectableLabel("數據源", LayoutOption.shortWidth);
            dataObj = EditorGUILayout.ObjectField(dataObj, typeof(LoadForceDataObject), false, LayoutOption.longWidth) as LoadForceDataObject;
        }
    }

3、繪製一個List添加功能按扭, 輸入框內放入創建的asset格式的數據源後,開始是沒有數據的,因此需要一個按扭來創建一個DataList是沒有數據的,因此需要一個按扭來創建一個DataList 並加入到這個對象中,效果如下圖所示。使用HorizontalScope這不必要,主要是考慮到還有一些其他的操作功能也可以加入到其中

  void DrawListsTools()
    {
        using (var scope = new EditorGUILayout.HorizontalScope())
        {
            GUI.backgroundColor = Color.blue;
            if (GUILayout.Button("+", LayoutOption.shortWidth))
            {
                dataLists.Add(new DataList());
            }
            GUI.backgroundColor = Color.white;

        }
    }

4、繪製可滑動的實體區域,bodyScorll 是一個全局變量,用來保存當前的滑動所處的狀態。dataLists是數據源對象所包含的所有DataList,在這其中將繪製的功能再次分爲繪製DataList的標題頭和數據體。

  void DrawBody()
    {
        using (var scope = new EditorGUILayout.ScrollViewScope(bodyScorll))
        {
            bodyScorll = scope.scrollPosition;
            foreach (var item in dataLists)
            {
                using (var vscope = new EditorGUILayout.VerticalScope())
                {
                    GUI.Box(vscope.rect, new GUIContent());
                    if (DrawListHeader(item))
                    {
                        DrawListBody(item);
                        GUILayout.Space(EditorGUIUtility.singleLineHeight);
                    }
                    else
                    {
                        continue;
                    }
                }
            }
            if (waitDeleteList != null)
            {
                dataLists.Remove(waitDeleteList);
            }
        }
    }

帶有返回值的LitstHeader繪製可以實現數據體的展開和隱藏

 bool DrawListHeader(DataList list)
    {
        using (var scope = new EditorGUILayout.HorizontalScope())
        {
            if (!viewDic.ContainsKey(list))
            {
                viewDic.Add(list, true);
            }
            if (viewDic[list] = GUILayout.Toggle(viewDic[list], list.name,LayoutOption.mediaHigh))
            {
                GUI.backgroundColor = Color.green;
                GUI.Box(scope.rect, "");
                GUI.backgroundColor = Color.white;
                EditorGUILayout.LabelField("ListName", LayoutOption.longWidth);
                list.name = EditorGUILayout.TextField(list.name, LayoutOption.longWidth);
                list.values = list.values ?? new List<DataItem>();

                GUI.backgroundColor = Color.blue;
                if (GUILayout.Button("+", LayoutOption.minWidth))
                {
                    list.values.Add(new DataItem());
                }
               
                GUI.backgroundColor = Color.white;
                return true;
            }
            else
            {
                GUI.backgroundColor = Color.red;
                if (GUILayout.Button("-", LayoutOption.minWidth))
                {
                    waitDeleteList = list;
                }
                GUI.backgroundColor = Color.white;
                return false;
            }
        }
    }

5、其他細節就沒有太多了,github地址爲:https://github.com/zouhunter/Editor_Extends(後續有相關的編輯器學習使用的腳本會同步到其中)

四、最終截圖:(在這樣的環境進行配製貌似省心了不少吧)


發佈了32 篇原創文章 · 獲贊 12 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章