Unity ScriptableObject 自動導出 .csv文件

ScriptableObject給客戶端用是很好用的,但是,如果給服務器端用,卻很麻煩,所以我寫了一個自動導出工具,可以以很小的代價,將ScriptableObject的部分字段自動導出到csv文件中,供服務器使用,這樣也避免了數據冗餘,同時避免策劃在填寫重複數據的時候出錯。


這裏說一下思想:

1-利用Attribute表明需要導出的字段和文件名

2-利用C#的反射機制,遍歷選擇的所有文件,找到需要導出的List,並且解析需要導出的泛型類,根據Attribute將其導出。


特性定義

[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)]
public class ExportToCSV : System.Attribute
{
    public string property_name;

    public ExportToCSV(string p_name) 
    {
        property_name = p_name;
    }
}

[System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = false)]
public class ExportList : System.Attribute
{
    public string file_name;

    public ExportList(string f_name) 
    {
        file_name = f_name;
    }
}


編輯器擴展

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Reflection;
using System.Reflection.Emit;
using System.IO;

public class ExportScriptableObjectToCSV : MonoBehaviour {

    private static Dictionary<string, List<string>> output_buffer = new Dictionary<string, List<string>>();

    [MenuItem("Custom Scriptable Asset/Configs/Export Select ConfigFiles")]
    public static void ExportAssetsToCSVs()
    {
        Object [] all_select = Selection.objects;

        Debug.Log(" All select count is " + all_select.Length);

        output_buffer.Clear();

        foreach (var source in all_select) 
        {
            ScriptableObject so = (ScriptableObject)source;
            if (so != null) 
            {
                ExportToCSV(so);
            }
        }
    }

    static void ExportToCSV( object source ) 
    {

        List<string> export_lines = new List<string>();

        foreach (FieldInfo fieldinfo in source.GetType().GetFields())
        {
            if (fieldinfo.FieldType.IsGenericType)
            {
                object[] attributes = fieldinfo.GetCustomAttributes(typeof(ExportList), false);

                foreach (var attribute_obj in attributes)
                {
                    if (attribute_obj is ExportList)
                    {
                        ExportList export_list = (ExportList)attribute_obj;
                        string file_name = export_list.file_name;
                        output_buffer[file_name] = new List<string>();

                        //retrive list object;
                        object list_object = fieldinfo.GetValue(source);
                        int item_count = (int)(fieldinfo.FieldType.GetProperty("Count").GetValue(list_object, null));

                        for (int i = 0; i < item_count; i++)
                        {
                            object listItem = fieldinfo.FieldType.GetProperty("Item").GetValue(list_object, new object[] { i });
                            if (i == 0) 
                            {
                                ProcessTitle(listItem, file_name);
                            }
                            ProcessValue(listItem, file_name);
                        }
                    }
                }
            }
        }

        foreach (var list in output_buffer) 
        {
            Debug.Log("Writing " + list.Key + "...");
            StreamWriter sw = new StreamWriter("Assets/Resources/Config/CSV/" + list.Key );

            foreach (var item in list.Value) 
            {
                sw.WriteLine(item);
            }

            sw.Flush();
            sw.Close();

            AssetDatabase.Refresh();
        }
    }

    static void ProcessTitle( object target, string file_name ) 
    {
        System.Type this_type = target.GetType();

        FieldInfo[] fields = this_type.GetFields();

        string title = "";

        foreach (var field in fields)
        {
            object[] attributes = field.GetCustomAttributes(typeof(ExportToCSV), false);
            foreach (var obj in attributes)
            {
                ExportToCSV etc = (ExportToCSV)obj;
                if (etc != null)
                {
                    title += etc.property_name + ",";
                }
            }
        }

        title = title.Substring(0, title.Length - 1);
        output_buffer[file_name].Add(title);        
    }

    static void ProcessValue( object target, string file_name ) 
    {
        System.Type this_type = target.GetType();

        FieldInfo[] fields = this_type.GetFields();

        string field_string = "";

        foreach (var field in fields)
        {
            object[] attributes = field.GetCustomAttributes(typeof(ExportToCSV), false);

            foreach (var obj in attributes)
            {
                ExportToCSV etc = (ExportToCSV)obj;
                if (etc != null)
                {
                    string val = field.GetValue(target).ToString();
                    field_string += val + ",";
                }
            }
        }

        field_string = field_string.Substring(0, field_string.Length - 1);
        output_buffer[file_name].Add(field_string);
    }
}

示例代碼:

public class HeadImageConfig : ScriptableObject
{
    [System.Serializable]
    public class HeadImageSet
    {
        [ExportToCSV("image_id")]
        public int head_image_id;
        [ExportToCSV("unlock_level")]
        public int unlock_level;
        [ExportToCSV("image_name")]
        public string head_image_name = "long life mao";
        public Sprite head_image;
        public bool under_development = false;
    }


    [ExportList("s_head_image.csv")]
    public List<HeadImageSet> head_images = new List<HeadImageSet>();



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