0评论

Unity3D资源管理——Excel表自动生成代码文件

文章来自https://blog.csdn.net/qq_28474981/article/details/82529529 2019-02-15 306浏览

想免费获取内部独家PPT资料库?观看行业大牛直播?点击加入腾讯游戏学院游戏策划行业精英群361498939

一、运行环境

1.1编辑器版本

使用Unity2017.3.1f

1.2 dll

(1)EPPlus

(2)Excel

(3)ICSharpCode.SharpZipLib

(4)System.Data(是mono文件夹底下的dll)

二、流程

1.读取目标excel文件,获取到它的前三行数据(分别为变量名,数据类型,中文名)

2.通过对前三行数据进行组合,形成可序列化的结构类以及存储多个具体数据的数据类

三、代码实现

3.1窗口

代码:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
public class ConfigEditorWindow: EditorWindow
{
    List<FileInfo> files = new List<FileInfo>();
    int lastSelectFileCount = 0;
    string lastSelectAssetGUID;
    [MenuItem("ResTools/Config/ConfigEditorWindow")]
    static void OpenConfigEditorWindow()
    {
        EditorWindow.GetWindow<ConfigEditorWindow>();
    }
    private void OnGUI()
    {
        GUILayout.BeginVertical();
        GUILayout.Space(10);
        GUILayout.Label("需要生成代码的配置文件列表");
        GUILayout.Space(15);
        if (Selection.assetGUIDs.Length != lastSelectFileCount || 
            (Selection.assetGUIDs.Length > 0 && lastSelectAssetGUID != Selection.assetGUIDs[Selection.assetGUIDs.Length - 1]))
        {
            files.Clear();
            lastSelectFileCount = Selection.assetGUIDs.Length;
            for (int i = 0; i < Selection.assetGUIDs.Length; i++)
            {
                FileInfo fileInfo =
                   new FileInfo(AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[i]));
                if (fileInfo.Exists)
                {
                    if (!files.Contains(fileInfo))
                        files.Add(fileInfo);
                }
            }
            lastSelectAssetGUID = Selection.assetGUIDs.Last<string>();
        }
        for (int i = 0; i < files.Count; i++)
        {
            if (files[i].Exists)
            {
                GUILayout.BeginHorizontal();
                GUILayout.Label("名称  :" + files[i].Name);
                GUILayout.EndHorizontal();
            }
        }
        GUILayout.BeginHorizontal();
        if (GUILayout.Button("生成"))
        {
            ConfigUtils.GenerateConfigsToCode(ConfigFileType.Excel, files,Application.dataPath+"/Scripts/Config");
        }
        GUILayout.EndHorizontal();
        GUILayout.EndVertical();
    }
}

实现效果:

3.2核心逻辑

代码:
using System.Text;
using ResourceSystem;
using System.Data;
using System.IO;
using UnityEngine;
using UnityEditor;
using System.Reflection;
public enum ConfigFileType
{
    Excel,
}
public class ConfigUtils
{
#region 自动生成配置代码
    static List<string> argsNames = new List<string>();
    static List<string> argsType = new List<string>();
    static List<string> argsChineseName = new List<string>();
    public static void GenerateConfigsToCode(ConfigFileType fileType, List<FileInfo> fileInfos, string targetPath)
    {
        for(int i=0;i< fileInfos.Count;i++)
        {
            GenerateConfigToCode(fileType, fileInfos[i], targetPath);
        }
    }
    public static void GenerateConfigToCode(ConfigFileType fileType,FileInfo fileInfo,string targetPath)
    {
        if (fileType== ConfigFileType.Excel)
        {
            GenerateExcelToCode(fileInfo.FullName, targetPath);
        }
    }
    private static void GenerateExcelToCode(string path,string targetPath)
    {
        DataTableCollection tables = ResourceSystemFacade.Inst.ReadExcel(path);
        argsNames.Clear();
        argsType.Clear();
        argsChineseName.Clear();
        int columns = tables[0].Columns.Count;//获取列数
        int rows = tables[0].Rows.Count;
        for (int n = 0; n < columns; n++)
        {
            argsNames.Add(tables[0].Rows[0][n].ToString());
            argsType.Add(tables[0].Rows[1][n].ToString());
            argsChineseName.Add(tables[0].Rows[2][n].ToString());
        }
        string fileName = Path.GetFileNameWithoutExtension(path);
        string code = GenerateCode(fileName);
        if (!string.IsNullOrEmpty(code))
        {
            DirectoryInfo info = new DirectoryInfo(targetPath);
            if (!info.Exists)
            {
                Directory.CreateDirectory(targetPath);
            }
            File.WriteAllText(targetPath +"/"+ fileName + "Info.cs", code);
        }
        else
        {
            DebugUtils.DebugError("生成代码有误");
        }
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="fileName"></param>
    /// <returns></returns>
    private static string GenerateCode(string fileName)
    {
        StringBuilder code = new StringBuilder();
        code.Append("using System;\nusing UnityEngine;\nusing System.Collections.Generic;\nusing ResourceSystem;\n\n");
        code.Append("public class ");
        code.Append(fileName);
        code.Append("Info:ScriptableObject,IDataCollectionTemplete\n{");
        code.Append("\n    public List<");
        code.Append(fileName);
        code.Append("Data>  Data = new List<");
        code.Append(fileName);
        code.Append("Data>();");
        code.Append("\n    /// <summary>\n ");
        code.Append("   /// 获得内容Type");
        code.Append("\n    /// </summary>\n    public Type GetContenType()\n    {");
        code.Append("\n        return typeof(");
        code.Append(fileName);
        code.Append("Data);");
        code.Append("\n    }");
        code.Append("\n    /// <summary>\n ");
        code.Append("   /// 转换成当前内容类型的列表");
        code.Append("\n    /// </summary>\n    public void ConvertToContentList(List<IDataTemplete> contents)\n    {");
        code.Append("\n       for(int i = 0; i < contents.Count; i++)\n       {");
        code.Append("\n           Data.Add((");
        code.Append(fileName);
        code.Append("Data)contents[i]);");
        code.Append("\n       }");
        code.Append("\n    }");
        code.Append("\n}\n\n");
        code.Append("\n[Serializable]\n");
        code.Append("public class ");
        code.Append(fileName);
        code.Append("Data:IDataTemplete\n{");
        for(int i = 0; i < argsNames.Count; i++)
        {
            code.Append("\n    /// <summary>\n ");
            code.Append("   /// ");
            code.Append(argsChineseName[i]);
            code.Append("\n    /// </summary>");
            code.Append("\n    public ");
            code.Append(argsType[i]);
            code.Append(" ");
            code.Append(argsNames[i]);
            code.Append("= default(");
            code.Append(argsType[i]);
            code.Append(");");
        }
        code.Append("\n    /// <summary>\n ");
        code.Append("   /// 反序列化");
        code.Append("\n    /// </summary>\n    public void DeSerialize(object[] content)\n    {");
        for (int i = 0; i < argsNames.Count; i++)
        {
            code.Append("\n        ");
            code.Append(argsNames[i]);
            if (argsType[i] == "int")
            {
                code.Append(" = Int32.Parse(content[");
                code.Append(i);
                code.Append("].ToString());");
            }
            else
            {
                code.Append(" = content[");
                code.Append(i);
                code.Append("].ToString();");
            }
        }
        code.Append("\n    }");
        code.Append("\n}");
        return code.ToString();
    }
    #endregion
}

实现效果:

由文件Test.xlsx

转化为数据文件
using System;
using UnityEngine;
using System.Collections.Generic;
using ResourceSystem;
public class TestInfo:ScriptableObject,IDataCollectionTemplete
{
    public List<TestData>  Data = new List<TestData>();
    /// <summary>
    /// 获得内容Type
    /// </summary>
    public Type GetContenType()
    {
        return typeof(TestData);
    }
    /// <summary>
    /// 转换成当前内容类型的列表
    /// </summary>
    public void ConvertToContentList(List<IDataTemplete> contents)
    {
       for(int i = 0; i < contents.Count; i++)
       {
           Data.Add((TestData)contents[i]);
       }
    }
}
[Serializable]
public class TestData:IDataTemplete
{
    /// <summary>
    /// 索引号
    /// </summary>
    public int ID= default(int);
    /// <summary>
    /// 名称
    /// </summary>
    public string Name= default(string);
    /// <summary>
    /// 反序列化
    /// </summary>
    public void DeSerialize(object[] content)
    {
        ID = Int32.Parse(content[0].ToString());
        Name = content[1].ToString();
    }
}

注:嫌Excel上两行的英文丑的话可以选择右键隐藏上面两行