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>();