解析流程:
1. 配置Excel
2. 读取解析Excel
3. 整理解析到的数据
4. 自动创建对应的C#类,继承ScriptableObject,声明变量,保存.cs文件
5. 自动创建ScriptableObject的Asset文件,并赋值,保存Asset文件
6. 在游戏直接使用ScriptableObject类
优点:
1. 每个Excel对应一个类,使用灵活,对Excel限制少
2. 自动创建C#类,不需要对每个Excel手动写代码,Excel修改后重新生成类即可
3. 自动创建ScriptableObject的Asset文件,自动对类字段赋值
4. 数据值直接写到ScriptableObject里,方便查看,可以手动修改调整,不需要每次改动都在Excel里操作
5. 在游戏内直接调用ScriptableObject类,不需要额外操作
具体操作:
1. 配置Excel
2. 读取Excel
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using Excel;
using System.Reflection;
using System;
//Excel中间数据
public class ExcelMediumData
{
//Excel名字
public string excelName;
//Dictionary<字段名称, 字段类型>,记录类的所有字段及其类型
public Dictionary<string, string> propertyNameTypeDic;
//List<一行数据>,List<Dictionary<字段名称, 一行的每个单元格字段值>>
//记录类的所有字段值,按行记录
public List<Dictionary<string, string>> allItemValueRowList;
}
public static class ExcelDataReader
{
//Excel第2行对应字段名称
const int excelNameRow = 2;
//Excel第4行对应字段类型
const int excelTypeRow = 4;
//Excel第5行及以后对应字段值
const int excelDataRow = 5;
//Excel读取路径
//public static string excelFilePath = Application.dataPath + "/Excel";
public static string excelFilePath = Application.dataPath.Replace("Assets", "Excel");
//自动生成C#类文件路径
static string excelCodePath = Application.dataPath + "/Script/Excel/AutoCreateCSCode";
//自动生成Asset文件路径
static string excelAssetPath = "Assets/Resources/ExcelAsset";
#region --- Read Excel ---
//创建Excel对应的C#类
public static void ReadAllExcelToCode()
{
//读取所有Excel文件
//指定目录中与指定的搜索模式和选项匹配的文件的完整名称(包含路径)的数组;如果未找到任何文件,则为空数组。
string[] excelFileFullPaths = Directory.GetFiles(excelFilePath, "*.xlsx");
if (excelFileFullPaths == null || excelFileFullPaths.Length == 0)
{
Debug.Log("Excel file count == 0");
return;
}
//遍历所有Excel,创建C#类
for (int i = 0; i < excelFileFullPaths.Length; i++)
{
ReadOneExcelToCode(excelFileFullPaths[i]);
}
}
//创建Excel对应的C#类
public static void ReadOneExcelToCode(string excelFileFullPath)
{
//解析Excel获取中间数据
ExcelMediumData excelMediumData = CreateClassCodeByExcelPath(excelFileFullPath);
if (excelMediumData != null)
{
//根据数据生成C#脚本
string classCodeStr = ExcelCodeCreater.CreateCodeStrByExcelData(excelMediumData);
if (!string.IsNullOrEmpty(classCodeStr))
{
//写文件,生成CSharp.cs
if (WriteCodeStrToSave(excelCodePath, excelMediumData.excelName + "ExcelData", classCodeStr))
{
Debug.Log("<color=green>Auto Create Excel Scripts Success : </color>" + excelMediumData.excelName);
return;
}
}
}
//生成失败
Debug.LogError("Auto Create Excel Scripts Fail : " + (excelMediumData == null ? "" : excelMediumData.excelName));
}
#endregion
#region --- Create Asset ---
//创建Excel对应的Asset数据文件
public static void CreateAllExcelAsset()
{
//读取所有Excel文件
//指定目录中与指定的搜索模式和选项匹配的文件的完整名称(包含路径)的数组;如果未找到任何文件,则为空数组。
string[] excelFileFullPaths = Directory.GetFiles(excelFilePath, "*.xlsx");
if (excelFileFullPaths == null || excelFileFullPaths.Length == 0)
{
Debug.Log("Excel file count == 0");
return;
}
//遍历所有Excel,创建Asset
for (int i = 0; i < excelFileFullPaths.Length; i++)
{
CreateOneExcelAsset(excelFileFullPaths[i]);
}
}
//创建Excel对应的Asset数据文件
public static void CreateOneExcelAsset(string excelFileFullPath)
{
//解析Excel获取中间数据
ExcelMediumData excelMediumData = CreateClassCodeByExcelPath(excelFileFullPath);
if (excelMediumData != null)
{
////获取当前程序集
//Assembly assembly = Assembly.GetExecutingAssembly();
////创建类的实例,返回为 object 类型,需要强制类型转换,assembly.CreateInstance("类的完全限定名(即包括命名空间)");
//object class0bj = assembly.CreateInstance(excelMediumData.excelName + "Assignment",true);
//必须遍历所有程序集来获得类型。当前在Assembly-CSharp-Editor中,目标类型在Assembly-CSharp中,不同程序将无法获取类型
Type type = null;
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
{
//查找目标类型
Type tempType = asm.GetType(excelMediumData.excelName + "AssetAssignment");
if (tempType != null)
{
type = tempType;
break;
}
}
if (type != null)
{
//反射获取方法
MethodInfo methodInfo = type.GetMethod("CreateAsset");
if (methodInfo != null)
{
methodInfo.Invoke(null, new object[] { excelMediumData.allItemValueRowList, excelAssetPath });
//创建Asset文件成功
Debug.Log("<color=green>Auto Create Excel Asset Success : </color>" + excelMediumData.excelName);
return;
}
}
}
//创建Asset文件失败
Debug.LogError("Auto Create Excel Asset Fail : " + (excelMediumData == null ? "" : excelMediumData.excelName));
}
#endregion
#region --- private ---
//解析Excel,创建中间数据
private static ExcelMediumData CreateClassCodeByExcelPath(string excelFileFullPath)
{
if (string.IsNullOrEmpty(excelFileFullPath))
return null;
excelFileFullPath = excelFileFullPath.Replace("\\", "/");
FileStream stream = File.Open(excelFileFullPath, FileMode.Open, FileAccess.Read);
if (stream == null)
return null;
//解析Excel
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
//无效Excel
if (excelReader == null || !excelReader.IsValid)
{
Debug.Log("Invalid excel : " + excelFileFullPath);
return null;
}
//<数据名称,数据类型>
KeyValuePair<string, string>[] propertyNameTypes = null;
//List<KeyValuePair<数据名称, 单元格数据值>[]>,所有数据值,按行记录
List<Dictionary<string, string>> allItemValueRowList = new List<Dictionary<string, string>>();
//每行数据数量
int propertyCount = 0;
//当前遍历行,从1开始
int curRowIndex = 1;
//开始读取,按行遍历
while (excelReader.Read())
{
if (excelReader.FieldCount == 0)
continue;
//读取一行的数据
string[] datas = new string[excelReader.FieldCount];
for (int j = 0; j < excelReader.FieldCount; ++j)
{
//赋值一行的每一个单元格数据
datas[j] = excelReader.GetString(j);
}
//空行/行第一个单元格为空,视为无效数据
if (datas.Length == 0 || string.IsNullOrEmpty(datas[0]))
{
curRowIndex++;
continue;
}
//数据行
if (curRowIndex >= excelDataRow)
{
//数据无效
if (propertyCount <= 0)
return null;
Dictionary<string, string> itemDic = new Dictionary<string, string>(propertyCount);
//遍历一行里的每个单元格数据
for (int j = 0; j < propertyCount; j++)
{
//判断长度
if (j < datas.Length)
itemDic[propertyNameTypes[j].Key] = datas[j];
else
itemDic[propertyNameTypes[j].Key] = null;
}
allItemValueRowList.Add(itemDic);
}
//数据名称行
else if (curRowIndex == excelNameRow)
{
//以数据名称确定每行的数据数量
propertyCount = datas.Length;
if (propertyCount <= 0)
return null;
//记录数据名称
propertyNameTypes = new KeyValuePair<string, string>[propertyCount];
for (int i = 0; i < propertyCount; i++)
{
propertyNameTypes[i] = new KeyValuePair<string, string>(datas[i], null);
}
}
//数据类型行
else if (curRowIndex == excelTypeRow)
{
//数据类型数量少于指定数量,数据无效
if (propertyCount <= 0 || datas.Length < propertyCount)
return null;
//记录数据名称及类型
for (int i = 0; i < propertyCount; i++)
{
propertyNameTypes[i] = new KeyValuePair<string, string>(propertyNameTypes[i].Key, datas[i]);
}
}
curRowIndex++;
}
if (propertyNameTypes.Length == 0 || allItemValueRowList.Count == 0)
return null;
ExcelMediumData excelMediumData = new ExcelMediumData();
//类名
excelMediumData.excelName = excelReader.Name;
//Dictionary<数据名称,数据类型>
excelMediumData.propertyNameTypeDic = new Dictionary<string, string>();
//转换存储格式
for (int i = 0; i < propertyCount; i++)
{
//数据名重复,数据无效
if (excelMediumData.propertyNameTypeDic.ContainsKey(propertyNameTypes[i].Key))
return null;
excelMediumData.propertyNameTypeDic.Add(propertyNameTypes[i].Key, propertyNameTypes[i].Value);
}
excelMediumData.allItemValueRowList = allItemValueRowList;
return excelMediumData;
}
//写文件
private static bool WriteCodeStrToSave(string writeFilePath, string codeFileName, string classCodeStr)
{
if (string.IsNullOrEmpty(codeFileName) || string.IsNullOrEmpty(classCodeStr))
return false;
//检查导出路径
if (!Directory.Exists(writeFilePath))
Directory.CreateDirectory(writeFilePath);
//写文件,生成CS类文件
StreamWriter sw = new StreamWriter(writeFilePath + "/" + codeFileName + ".cs");
sw.WriteLine(classCodeStr);
sw.Close();
//
UnityEditor.AssetDatabase.Refresh();
return true;
}
#endregion
}
#endif
3. 自动生成C#类和Asset文件
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Text;
public class ExcelCodeCreater
{
#region --- Create Code ---
//创建代码,生成数据C#类
public static string CreateCodeStrByExcelData(ExcelMediumData excelMediumData)
{
if (excelMediumData == null)
return null;
//Excel名字
string excelName = excelMediumData.excelName;
if (string.IsNullOrEmpty(excelName))
return null;
//Dictionary<字段名称, 字段类型>
Dictionary<string, string> propertyNameTypeDic = excelMediumData.propertyNameTypeDic;
if (propertyNameTypeDic == null || propertyNameTypeDic.Count == 0)
return null;
//List<一行数据>,List<Dictionary<字段名称, 一行的每个单元格字段值>>
List<Dictionary<string, string>> allItemValueRowList = excelMediumData.allItemValueRowList;
if (allItemValueRowList == null || allItemValueRowList.Count == 0)
return null;
//行数据类名
string itemClassName = excelName + "ExcelItem";
//整体数据类名
string dataClassName = excelName + "ExcelData";
//生成类
StringBuilder classSource = new StringBuilder();
classSource.Append("/*Auto Create, Don't Edit !!!*/\n");
classSource.Append("\n");
//添加引用
classSource.Append("using UnityEngine;\n");
classSource.Append("using System.Collections.Generic;\n");
classSource.Append("using System;\n");
classSource.Append("using System.IO;\n");
classSource.Append("\n");
//生成行数据类,记录每行数据
classSource.Append(CreateExcelRowItemClass(itemClassName, propertyNameTypeDic));
classSource.Append("\n");
//生成整体数据类,记录整个Excel的所有行数据
classSource.Append(CreateExcelDataClass(dataClassName, itemClassName));
classSource.Append("\n");
//生成Asset操作类,用于自动创建Excel对应的Asset文件并赋值
classSource.Append(CreateExcelAssetClass(excelMediumData));
classSource.Append("\n");
return classSource.ToString();
}
//----------
//生成行数据类
private static StringBuilder CreateExcelRowItemClass(string itemClassName, Dictionary<string, string> propertyNameTypeDic)
{
//生成Excel行数据类
StringBuilder classSource = new StringBuilder();
classSource.Append("[Serializable]\n");
classSource.Append("public class " + itemClassName + " : ExcelItemBase\n");
classSource.Append("{\n");
//声明所有字段
foreach (var item in propertyNameTypeDic)
{
classSource.Append(CreateCodeProperty(item.Key, item.Value));
}
classSource.Append("}\n");
return classSource;
}
//声明行数据类字段
private static string CreateCodeProperty(string name, string type)
{
if (string.IsNullOrEmpty(name))
return null;
if (name == "id")
return null;
//判断字段类型
if (type == "int" || type == "Int" || type == "INT")
type = "int";
else if (type == "float" || type == "Float" || type == "FLOAT")
type = "float";
else if (type == "bool" || type == "Bool" || type == "BOOL")
type = "bool";
else
type = "string";
//声明
string propertyStr = "\tpublic " + type + " " + name + ";\n";
return propertyStr;
}
//----------
//生成数据类
private static StringBuilder CreateExcelDataClass(string dataClassName, string itemClassName)
{
StringBuilder classSource = new StringBuilder();
classSource.Append("[CreateAssetMenu(fileName = \"" + dataClassName + "\", menuName = \"Excel To ScriptableObject/Create " + dataClassName + "\", order = 1)]\n");
classSource.Append("public class " + dataClassName + " : ExcelDataBase<" + itemClassName + ">\n");
classSource.Append("{\n");
//声明字段,行数据类数组
//classSource.Append("\tpublic " + itemClassName + "[] items;\n");
classSource.Append("}\n");
return classSource;
}
//----------
//生成Asset操作类
private static StringBuilder CreateExcelAssetClass(ExcelMediumData excelMediumData)
{
if (excelMediumData == null)
return null;
string excelName = excelMediumData.excelName;
if (string.IsNullOrEmpty(excelName))
return null;
Dictionary<string, string> propertyNameTypeDic = excelMediumData.propertyNameTypeDic;
if (propertyNameTypeDic == null || propertyNameTypeDic.Count == 0)
return null;
List<Dictionary<string, string>> allItemValueRowList = excelMediumData.allItemValueRowList;
if (allItemValueRowList == null || allItemValueRowList.Count == 0)
return null;
string itemClassName = excelName + "ExcelItem";
string dataClassName = excelName + "ExcelData";
StringBuilder classSource = new StringBuilder();
classSource.Append("#if UNITY_EDITOR\n");
//类名
classSource.Append("public class " + excelName + "AssetAssignment\n");
classSource.Append("{\n");
//方法名
classSource.Append("\tpublic static bool CreateAsset(List<Dictionary<string, string>> allItemValueRowList, string excelAssetPath)\n");
//方法体,若有需要可加入try/catch
classSource.Append("\t{\n");
classSource.Append("\t\tif (allItemValueRowList == null || allItemValueRowList.Count == 0)\n");
classSource.Append("\t\t\treturn false;\n");
classSource.Append("\t\tint rowCount = allItemValueRowList.Count;\n");
classSource.Append("\t\t" + itemClassName + "[] items = new " + itemClassName + "[rowCount];\n");
classSource.Append("\t\tfor (int i = 0; i < items.Length; i++)\n");
classSource.Append("\t\t{\n");
classSource.Append("\t\t\titems[i] = new " + itemClassName + "();\n");
foreach (var item in propertyNameTypeDic)
{
classSource.Append("\t\t\titems[i]." + item.Key + " = ");
classSource.Append(AssignmentCodeProperty("allItemValueRowList[i][\"" + item.Key + "\"]", propertyNameTypeDic[item.Key]));
classSource.Append(";\n");
}
classSource.Append("\t\t}\n");
classSource.Append("\t\t" + dataClassName + " excelDataAsset = ScriptableObject.CreateInstance<" + dataClassName + ">();\n");
classSource.Append("\t\texcelDataAsset.items = items;\n");
classSource.Append("\t\tif (!Directory.Exists(excelAssetPath))\n");
classSource.Append("\t\t\tDirectory.CreateDirectory(excelAssetPath);\n");
classSource.Append("\t\tstring pullPath = excelAssetPath + \"/\" + typeof(" + dataClassName + ").Name + \".asset\";\n");
classSource.Append("\t\tUnityEditor.AssetDatabase.DeleteAsset(pullPath);\n");
classSource.Append("\t\tUnityEditor.AssetDatabase.CreateAsset(excelDataAsset, pullPath);\n");
classSource.Append("\t\tUnityEditor.AssetDatabase.Refresh();\n");
classSource.Append("\t\treturn true;\n");
classSource.Append("\t}\n");
//
classSource.Append("}\n");
classSource.Append("#endif\n");
return classSource;
}
//声明Asset操作类字段
private static string AssignmentCodeProperty(string stringValue, string type)
{
//判断类型
if (type == "int" || type == "Int" || type == "INT")
{
return "Convert.ToInt32(" + stringValue + ")";
}
else if (type == "float" || type == "Float" || type == "FLOAT")
{
return "Convert.ToSingle(" + stringValue + ")";
}
else if (type == "bool" || type == "Bool" || type == "BOOL")
{
return "Convert.ToBoolean(" + stringValue + ")";
}
else
return stringValue;
}
#endregion
}
#endif
4. 编写操作面板窗口
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
using System.Linq;
public class BuildExcelEditor : Editor
{
}
public class BuildExcelWindow : EditorWindow
{
//[MenuItem("MyTools/Excel/Build Script")]
//public static void CreateExcelCode()
//{
// ExcelDataReader.ReadAllExcelToCode();
//}
//[MenuItem("MyTools/Excel/Build Asset")]
//public static void CreateExcelAssset()
//{
// ExcelDataReader.CreateAllExcelAsset();
//}
[MenuItem("MyTools/Excel/Build Window")]
public static void ShowExcelWindow()
{
//显示操作窗口方式一
//BuildExcelWindow buildExcelWindow = GetWindow<BuildExcelWindow>();
//buildExcelWindow.Show();
//显示操作窗口方式二
EditorWindow.GetWindow(typeof(BuildExcelWindow));
}
private string showNotify;
private Vector2 scrollPosition = Vector2.zero;
private List<string> fileNameList = new List<string>();
private List<string> filePathList = new List<string>();
private void Awake()
{
titleContent.text = "Excel数据读取";
}
private void OnEnable()
{
showNotify = "";
GetExcelFile();
}
private void OnDisable()
{
showNotify = "";
fileNameList.Clear();
filePathList.Clear();
}
private void OnGUI()
{
scrollPosition = GUILayout.BeginScrollView(scrollPosition,
GUILayout.Width(position.width), GUILayout.Height(position.height));
//自动创建C#脚本
GUILayout.Space(10);
GUILayout.Label("Excel To Script");
for (int i = 0; i < fileNameList.Count; i++)
{
if (GUILayout.Button(fileNameList[i], GUILayout.Width(200), GUILayout.Height(30)))
{
SelectExcelToCodeByIndex(i);
}
}
if (GUILayout.Button("All Excel", GUILayout.Width(200), GUILayout.Height(30)))
{
SelectExcelToCodeByIndex(-1);
}
//自动创建Asset文件
GUILayout.Space(20);
GUILayout.Label("Script To Asset");
for (int i = 0; i < fileNameList.Count; i++)
{
if (GUILayout.Button(fileNameList[i], GUILayout.Width(200), GUILayout.Height(30)))
{
SelectCodeToAssetByIndex(i);
}
}
if (GUILayout.Button("All Excel", GUILayout.Width(200), GUILayout.Height(30)))
{
SelectCodeToAssetByIndex(-1);
}
//
GUILayout.Space(20);
GUILayout.Label(showNotify);
//
GUILayout.EndScrollView();
//this.Repaint();
}
//读取指定路径下的Excel文件名
private void GetExcelFile()
{
fileNameList.Clear();
filePathList.Clear();
if (!Directory.Exists(ExcelDataReader.excelFilePath))
{
showNotify = "无效路径:" + ExcelDataReader.excelFilePath;
return;
}
string[] excelFileFullPaths = Directory.GetFiles(ExcelDataReader.excelFilePath, "*.xlsx");
if (excelFileFullPaths == null || excelFileFullPaths.Length == 0)
{
showNotify = ExcelDataReader.excelFilePath + "路径下没有找到Excel文件";
return;
}
filePathList.AddRange(excelFileFullPaths);
for (int i = 0; i < filePathList.Count; i++)
{
string fileName = filePathList[i].Split('/').LastOrDefault();
fileName = filePathList[i].Split('\\').LastOrDefault();
fileNameList.Add(fileName);
}
showNotify = "找到Excel文件:" + fileNameList.Count + "个";
}
//自动创建C#脚本
private void SelectExcelToCodeByIndex(int index)
{
if (index >= 0 && index < filePathList.Count)
{
string fullPath = filePathList[index];
ExcelDataReader.ReadOneExcelToCode(fullPath);
}
else
{
ExcelDataReader.ReadAllExcelToCode();
}
}
//自动创建Asset文件
private void SelectCodeToAssetByIndex(int index)
{
if (index >= 0 && index < filePathList.Count)
{
string fullPath = filePathList[index];
ExcelDataReader.CreateOneExcelAsset(fullPath);
}
else
{
ExcelDataReader.CreateAllExcelAsset();
}
}
}
#endif
5. 操作成功,游戏内使用数据
表格数据类基类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class ExcelDataBase<T> : ScriptableObject where T : ExcelItemBase
{
public T[] items;
public T GetExcelItem(string targetId)
{
if(items != null && items.Length > 0)
{
return items.FirstOrDefault(item => item.id == targetId);
}
return null;
}
}
public class ExcelItemBase
{
public string id;
}
自动创建的C#类:
/*Auto Create, Don't Edit !!!*/
using UnityEngine;
using System.Collections.Generic;
using System;
using System.IO;
[Serializable]
public class RoleParameExcelItem : ExcelItemBase
{
public int attack;
public int maxHealth;
public int energySpeed;
public int maxEnergy;
public float mass;
public int maxSpeed;
public int acceleration;
public float critProbability;
public float critValue;
public float angryTime;
public float angrySpeed;
public float bounceTime;
public float resist;
public int skillLevel;
}
[CreateAssetMenu(fileName = "RoleParameExcelData", menuName = "Excel To ScriptableObject/Create RoleParameExcelData", order = 1)]
public class RoleParameExcelData : ExcelDataBase<RoleParameExcelItem>
{
}
#if UNITY_EDITOR
public class RoleParameAssetAssignment
{
public static bool CreateAsset(List<Dictionary<string, string>> allItemValueRowList, string excelAssetPath)
{
if (allItemValueRowList == null || allItemValueRowList.Count == 0)
return false;
int rowCount = allItemValueRowList.Count;
RoleParameExcelItem[] items = new RoleParameExcelItem[rowCount];
for (int i = 0; i < items.Length; i++)
{
items[i] = new RoleParameExcelItem();
items[i].id = allItemValueRowList[i]["id"];
items[i].attack = Convert.ToInt32(allItemValueRowList[i]["attack"]);
items[i].maxHealth = Convert.ToInt32(allItemValueRowList[i]["maxHealth"]);
items[i].energySpeed = Convert.ToInt32(allItemValueRowList[i]["energySpeed"]);
items[i].maxEnergy = Convert.ToInt32(allItemValueRowList[i]["maxEnergy"]);
items[i].mass = Convert.ToSingle(allItemValueRowList[i]["mass"]);
items[i].maxSpeed = Convert.ToInt32(allItemValueRowList[i]["maxSpeed"]);
items[i].acceleration = Convert.ToInt32(allItemValueRowList[i]["acceleration"]);
items[i].critProbability = Convert.ToSingle(allItemValueRowList[i]["critProbability"]);
items[i].critValue = Convert.ToSingle(allItemValueRowList[i]["critValue"]);
items[i].angryTime = Convert.ToSingle(allItemValueRowList[i]["angryTime"]);
items[i].angrySpeed = Convert.ToSingle(allItemValueRowList[i]["angrySpeed"]);
items[i].bounceTime = Convert.ToSingle(allItemValueRowList[i]["bounceTime"]);
items[i].resist = Convert.ToSingle(allItemValueRowList[i]["resist"]);
items[i].skillLevel = Convert.ToInt32(allItemValueRowList[i]["skillLevel"]);
}
RoleParameExcelData excelDataAsset = ScriptableObject.CreateInstance<RoleParameExcelData>();
excelDataAsset.items = items;
if (!Directory.Exists(excelAssetPath))
Directory.CreateDirectory(excelAssetPath);
string pullPath = excelAssetPath + "/" + typeof(RoleParameExcelData).Name + ".asset";
UnityEditor.AssetDatabase.DeleteAsset(pullPath);
UnityEditor.AssetDatabase.CreateAsset(excelDataAsset, pullPath);
UnityEditor.AssetDatabase.Refresh();
return true;
}
}
#endif
自动创建的ScriptableObject对应Asset文件
测试用管理类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class ExcelManager : CSSingleton<ExcelManager>
{
Dictionary<Type, ExcelDataBase<ExcelItemBase>> excelDataDic = new Dictionary<Type, ExcelDataBase<ExcelItemBase>>();
public void Init()
{
}
public T GetExcelData<T, V>() where T : ExcelDataBase<V> where V : ExcelItemBase
{
Type type = typeof(T);
if (excelDataDic.ContainsKey(type))
return excelDataDic[type] as T;
T excelData = LoadManager.ResourcesLoad<T>(ConstConfig.excelAssetResourcesPath, type.Name);
if (excelData != null)
excelDataDic.Add(type, excelData as ExcelDataBase<ExcelItemBase>);
return excelData;
}
public V GetExcelItem<T, V>(string targetId) where T : ExcelDataBase<V> where V : ExcelItemBase
{
Type type = typeof(T);
T excelData = GetExcelData<T, V>();
if (excelData != null)
return excelData.GetExcelItem(targetId);
return null;
}
}
测试游戏内使用
public class ExcelTest : MonoBehaviour
{
void Start()
{
RoleParameExcelData roleParameExcelData = Resources.Load<RoleParameExcelData>("ExcelAsset/RoleParameExcelData");
if(roleParameExcelData != null)
{
for (int i = 0; i < roleParameExcelData.items.Length; i++)
{
Debug.Log(roleParameExcelData.items[i].id);
}
}
}
}