


Excel注释操作:

行数据类,对应每一行数据:
- [Serializable]
- public class TestConfigExcelItem : ExcelItemBase
- {
- /// <summary>
- /// 数据id
- /// </summary>>
- public int id;
- /// <summary>
- /// 字符串
- /// </summary>>
- public string testString;
- /// <summary>
- /// Int
- /// </summary>>
- public int testInt;
- /// <summary>
- /// Float
- /// </summary>>
- public float testFloat;
- }
完整数据类,包含所有行的数据、初始化函数、Get函数:
- public class TestConfigExcelData : ExcelDataBase<TestConfigExcelItem>
- {
- public TestConfigExcelItem[] items;
-
- public Dictionary<int,TestConfigExcelItem> itemDic = new Dictionary<int,TestConfigExcelItem>();
-
- public void Init()
- {
- itemDic.Clear();
- if(items != null && items.Length > 0)
- {
- for(int i = 0; i < items.Length; i++)
- {
- itemDic.Add(items[i].id, items[i]);
- }
- }
- }
-
- public TestConfigExcelItem GetTestConfigExcelItem(int id)
- {
- if(itemDic.ContainsKey(id))
- return itemDic[id];
- else
- return null;
- }
- #region --- Get Method ---
-
- public string GetTestString(int id)
- {
- var item = GetTestConfigExcelItem(id);
- if(item == null)
- return default;
- return item.testString;
- }
-
- // ··· ···
-
- #endregion
- }
| 字符串 | testString | 字符串数组 | testStringArray | 字符串二维数组 | testStringArray2 |
| Int | testInt | Int数组 | testIntArray | Int二维数组 | testIntArray2 |
| Float | testFloat | Float数组 | testFloatArray | Float二维数组 | testFloatArray2 |
| Bool | testBool | Bool数组 | testBoolArray | Bool二维数组 | testBoolArray2 |
| Enum|枚举名(或枚举值) | testEnum | Enum数组 | testEnumArray | Enum二维数组 | 不支持 |
| Vector2 | testVector2 | Vector2数组 | testVector2Array | Vector2二维数组 | testVector2Array2 |
| Vector3 | testVector3 | Vector3数组 | testVector3Array | Vector3二维数组 | testVector3Array2 |
| Vector2Int | testVector2Int | Vector2Int数组 | testVector2IntArray | Vector2Int二维数组 | testVector2IntArray2 |
| Vector3Int | testVector3Int | Vector3Int数组 | testVector3IntArray | Vector3Int二维数组 | testVector3IntArray2 |
| Color | testColor | Color数组 | testColorArray | Color二维数组 | testColorArray2 |
| Color32 | testColor32 | Color32数组 | testColor32Array | Color32二维数组 | testColor32Array2 |
因为Unity不能序列化二维数组,这里改成一维数组+结构体的方式实现:
- [Serializable]
- public struct StringArr
- {
- public string[] array;
- }
-
- //二维数组表示方式: StringArr[]
在自动生成数据的C#类时,会同步生成Asset文件的创建类,用于自动创建Asset文件并序列化数据。



- using UnityEngine;
- using UnityEditor;
- using System.IO;
- using System.Collections.Generic;
- using System.Linq;
-
- public class BuildExcelWindow : EditorWindow
- {
- [MenuItem("MyTools/Excel Window",priority = 100)]
- public static void ShowReadExcelWindow()
- {
- BuildExcelWindow window = GetWindow<BuildExcelWindow>(true);
- window.Show();
- window.minSize = new Vector2(475,475);
- }
-
- //Excel读取路径,绝对路径,放在Assets同级路径
- private static string excelReadAbsolutePath;
-
- //自动生成C#类文件路径,绝对路径
- private static string scriptSaveAbsolutePath;
- private static string scriptSaveRelativePath;
- //自动生成Asset文件路径,相对路径
- private static string assetSaveRelativePath;
-
- private List<string> fileNameList = new List<string>();
- private List<string> filePathList = new List<string>();
-
- private void Awake()
- {
- titleContent.text = "Excel配置表读取";
-
- excelReadAbsolutePath = Application.dataPath.Replace("Assets","Excel");
- scriptSaveAbsolutePath = Application.dataPath + CheckEditorPath("/Script/Excel/AutoCreateCSCode");
- scriptSaveRelativePath = CheckEditorPath("Assets/Script/Excel/AutoCreateCSCode");
- assetSaveRelativePath = CheckEditorPath("Assets/AssetData/Excel/AutoCreateAsset");
- }
-
- private void OnEnable()
- {
- RefreshExcelFile();
- }
-
- private void OnDisable()
- {
- fileNameList.Clear();
- filePathList.Clear();
- }
-
- private Vector2 scrollPosition = Vector2.zero;
- private void OnGUI()
- {
- GUILayout.Space(10);
-
- scrollPosition = GUILayout.BeginScrollView(scrollPosition,GUILayout.Width(position.width),GUILayout.Height(position.height));
-
- //展示路径
- GUILayout.BeginHorizontal(GUILayout.Height(20));
- if(GUILayout.Button("Excel读取路径",GUILayout.Width(100)))
- {
- EditorUtility.OpenWithDefaultApp(excelReadAbsolutePath);
- Debug.Log(excelReadAbsolutePath);
- }
- if(GUILayout.Button("Script保存路径",GUILayout.Width(100)))
- {
- SelectObject(scriptSaveRelativePath);
- }
- if(GUILayout.Button("Asset保存路径",GUILayout.Width(100)))
- {
- SelectObject(assetSaveRelativePath);
- }
- GUILayout.EndHorizontal();
-
- GUILayout.Space(5);
-
- //Excel列表
-
- GUILayout.Label("Excel列表:");
- for(int i = 0; i < fileNameList.Count; i++)
- {
- GUILayout.BeginHorizontal("Box",GUILayout.Height(40));
-
- GUILayout.Label($"{i}:","Titlebar Foldout",GUILayout.Width(30),GUILayout.Height(35));
- GUILayout.Box(fileNameList[i],"MeTransitionBlock",GUILayout.MinWidth(200),GUILayout.Height(35));
- GUILayout.Space(10);
-
- //生成CS代码
- if(GUILayout.Button("Create Script",GUILayout.Width(100),GUILayout.Height(30)))
- {
- ExcelDataReader.ReadOneExcelToCode(filePathList[i],scriptSaveAbsolutePath);
- }
- //生成Asset文件
- if(GUILayout.Button("Create Asset",GUILayout.Width(100),GUILayout.Height(30)))
- {
- ExcelDataReader.CreateOneExcelAsset(filePathList[i],assetSaveRelativePath);
- }
-
- GUILayout.EndHorizontal();
- GUILayout.Space(5);
- }
- GUILayout.Space(10);
-
- //一键处理所有Excel
-
- GUILayout.Label("一键操作:");
- GUILayout.BeginHorizontal("Box",GUILayout.Height(40));
-
- GUILayout.Label("all","Titlebar Foldout",GUILayout.Width(30),GUILayout.Height(35));
- GUILayout.Box("All Excel","MeTransitionBlock",GUILayout.MinWidth(200),GUILayout.Height(35));
- GUILayout.Space(10);
-
- if(GUILayout.Button("Create Script",GUILayout.Width(100),GUILayout.Height(30)))
- {
- ExcelDataReader.ReadAllExcelToCode(excelReadAbsolutePath,scriptSaveAbsolutePath);
- }
- if(GUILayout.Button("Create Asset",GUILayout.Width(100),GUILayout.Height(30)))
- {
- ExcelDataReader.CreateAllExcelAsset(excelReadAbsolutePath,assetSaveRelativePath);
- }
- GUILayout.EndHorizontal();
-
- //
- GUILayout.Space(20);
- //
- GUILayout.EndScrollView();
- }
-
- //读取指定路径下的Excel文件名
- private void RefreshExcelFile()
- {
- fileNameList.Clear();
- filePathList.Clear();
-
- if(!Directory.Exists(excelReadAbsolutePath))
- {
- Debug.LogError("无效路径:" + excelReadAbsolutePath);
- return;
- }
- string[] excelFileFullPaths = Directory.GetFiles(excelReadAbsolutePath,"*.xlsx");
-
- if(excelFileFullPaths == null || excelFileFullPaths.Length == 0)
- {
- Debug.LogError(excelReadAbsolutePath + "路径下没有找到Excel文件");
- return;
- }
-
- filePathList.AddRange(excelFileFullPaths);
- for(int i = 0; i < filePathList.Count; i++)
- {
- fileNameList.Add(Path.GetFileName(filePathList[i]));
- }
- Debug.Log("找到Excel文件:" + fileNameList.Count + "个");
- }
-
- private void SelectObject(string targetPath)
- {
- Object targetObj = AssetDatabase.LoadAssetAtPath<Object>(targetPath);
- EditorGUIUtility.PingObject(targetObj);
- Selection.activeObject = targetObj;
- Debug.Log(targetPath);
- }
-
- private static string CheckEditorPath(string path)
- {
- #if UNITY_EDITOR_WIN
- return path.Replace("/","\\");
- #elif UNITY_EDITOR_OSX
- return path.Replace("\\","/");
- #else
- return path;
- #endif
- }
- }
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using System.IO;
- using Excel;
- using System.Reflection;
- using System;
- using System.Linq;
-
- public class ExcelDataReader
- {
- //Excel第1行对应特殊标记
- private const int specialSignRow = 0;
- //Excel第2行对应中文说明
- private const int excelNodeRow = 1;
- //Excel第3行对应字段名称
- private const int excelNameRow = 2;
- //Excel第4行对应字段类型
- private const int excelTypeRow = 3;
- //Excel第5行及以后对应字段值
- private const int excelDataRow = 4;
-
- //标记注释行/列
- private const string annotationSign = "//";
-
- #region --- Read Excel ---
-
- //创建Excel对应的C#类
- public static void ReadAllExcelToCode(string allExcelPath,string codeSavePath)
- {
- //读取所有Excel文件
- //指定目录中与指定的搜索模式和选项匹配的文件的完整名称(包含路径)的数组;如果未找到任何文件,则为空数组。
- string[] excelFileFullPaths = Directory.GetFiles(allExcelPath,"*.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],codeSavePath);
- }
- }
-
- //创建Excel对应的C#类
- public static void ReadOneExcelToCode(string excelFullPath,string codeSavePath)
- {
- //解析Excel获取中间数据
- ExcelMediumData excelMediumData = CreateClassCodeByExcelPath(excelFullPath);
- if(excelMediumData == null)
- {
- Debug.LogError($"读取Excel失败 : {excelFullPath}");
- return;
- }
- if(!excelMediumData.isValid)
- {
- Debug.LogError($"读取Excel失败,Excel标记失效 : {excelMediumData.excelName}");
- return;
- }
-
- if(!excelMediumData.isCreateCSharp && !excelMediumData.isCreateAssignment)
- {
- Debug.LogError($"读取Excel失败,Excel不允许生成CSCode : {excelMediumData.excelName}");
- return;
- }
-
- //根据数据生成C#脚本
- string classCodeStr = ExcelCodeCreater.CreateCodeStrByExcelData(excelMediumData);
- if(string.IsNullOrEmpty(classCodeStr))
- {
- Debug.LogError($"解析Excel失败 : {excelMediumData.excelName}");
- return;
- }
-
- //检查导出路径
- if(!Directory.Exists(codeSavePath))
- Directory.CreateDirectory(codeSavePath);
- //类名
- string codeFileName = excelMediumData.excelName + "ExcelData";
- //写文件,生成CS类文件
- StreamWriter sw = new StreamWriter($"{codeSavePath}/{codeFileName}.cs");
- sw.WriteLine(classCodeStr);
- sw.Close();
- //
- UnityEditor.AssetDatabase.SaveAssets();
- UnityEditor.AssetDatabase.Refresh();
- //
- Debug.Log($"生成Excel的CS成功 : {excelMediumData.excelName}");
- }
-
- #endregion
-
- #region --- Create Asset ---
-
- //创建Excel对应的Asset数据文件
- public static void CreateAllExcelAsset(string allExcelPath,string assetSavePath)
- {
- //读取所有Excel文件
- //指定目录中与指定的搜索模式和选项匹配的文件的完整名称(包含路径)的数组;如果未找到任何文件,则为空数组。
- string[] excelFileFullPaths = Directory.GetFiles(allExcelPath,"*.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],assetSavePath);
- }
- }
-
- //创建Excel对应的Asset数据文件
- public static void CreateOneExcelAsset(string excelFullPath,string assetSavePath)
- {
- //解析Excel获取中间数据
- ExcelMediumData excelMediumData = CreateClassCodeByExcelPath(excelFullPath);
- if(excelMediumData == null)
- {
- Debug.LogError($"读取Excel失败 : {excelFullPath}");
- return;
- }
- if(!excelMediumData.isValid)
- {
- Debug.LogError($"读取Excel失败,Excel标记失效 : {excelMediumData.excelName}");
- return;
- }
-
- if(!excelMediumData.isCreateAsset)
- {
- Debug.LogError($"读取Excel失败,Excel不允许生成Asset : {excelMediumData.excelName}");
- return;
- }
-
- 获取当前程序集
- //Assembly assembly = Assembly.GetExecutingAssembly();
- 创建类的实例,返回为 object 类型,需要强制类型转换,assembly.CreateInstance("类的完全限定名(即包括命名空间)");
- //object class0bj = assembly.CreateInstance(excelMediumData.excelName + "Assignment",true);
-
- //必须遍历所有程序集来获得类型。当前在Assembly-CSharp-Editor中,目标类型在Assembly-CSharp中,不同程序将无法获取类型
- Type assignmentType = null;
- string assetAssignmentName = excelMediumData.excelName + "AssetAssignment";
- foreach(var asm in AppDomain.CurrentDomain.GetAssemblies())
- {
- //查找目标类型
- Type tempType = asm.GetType(assetAssignmentName);
- if(tempType != null)
- {
- assignmentType = tempType;
- break;
- }
- }
- if(assignmentType == null)
- {
- Debug.LogError($"创界Asset失败,未找到Asset生成类 : {excelMediumData.excelName}");
- return;
- }
-
- //反射获取方法
- MethodInfo methodInfo = assignmentType.GetMethod("CreateAsset");
- if(methodInfo == null)
- {
- if(assignmentType == null)
- {
- Debug.LogError($"创界Asset失败,未找到Asset创建函数 : {excelMediumData.excelName}");
- return;
- }
- }
-
- methodInfo.Invoke(null,new object[] { excelMediumData,assetSavePath });
- //创建Asset文件成功
- Debug.Log($"生成Excel的Asset成功 : {excelMediumData.excelName}");
- }
-
- #endregion
-
- #region --- private ---
-
- //解析Excel,创建中间数据
- private static ExcelMediumData CreateClassCodeByExcelPath(string excelFileFullPath)
- {
- if(string.IsNullOrEmpty(excelFileFullPath))
- return null;
-
- excelFileFullPath = excelFileFullPath.Replace("\\","/");
- //读取Excel
- 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;
- }
-
- Debug.Log("开始解析Excel : " + excelReader.Name);
-
- //记录Excel数据
- ExcelMediumData excelMediumData = new ExcelMediumData();
-
- //Excel名字
- excelMediumData.excelName = excelReader.Name;
-
- //当前遍历的行
- int curRowIndex = 0;
- //开始读取,按行遍历
- while(excelReader.Read())
- {
- //这一行没有读取到数据,视为无效行数据
- if(excelReader.FieldCount <= 0)
- {
- curRowIndex++;
- continue;
- }
- //读取每一行的完整数据
- string[] datas = new string[excelReader.FieldCount];
- for(int j = 0; j < excelReader.FieldCount; ++j)
- {
- //可以直接读取指定类型数据,不过只支持有限数据类型,这里统一读取string,然后再数据转化
- //excelReader.GetInt32(j); excelReader.GetFloat(j);
-
- //读取每一个单元格数据
- datas[j] = excelReader.GetString(j);
- }
-
- switch(curRowIndex)
- {
- case specialSignRow:
- //特殊标记行
- string specialSignStr = datas[0];
- if(specialSignStr.Length >= 4)
- {
- excelMediumData.isValid = specialSignStr[0] == 'T';
- excelMediumData.isCreateCSharp = specialSignStr[1] == 'T';
- excelMediumData.isCreateAssignment = specialSignStr[2] == 'T';
- excelMediumData.isCreateAsset = specialSignStr[3] == 'T';
- }
- else
- {
- Debug.LogError("未解析到特殊标记");
- }
- break;
- case excelNodeRow:
- //数据注释行
- excelMediumData.propertyNodeArray = datas;
- break;
- case excelNameRow:
- //数据名称行
- excelMediumData.propertyNameArray = datas;
- //注释列号
- for(int i = 0; i < datas.Length; i++)
- {
- if(string.IsNullOrEmpty(datas[i]) || datas[i].StartsWith(annotationSign))
- excelMediumData.annotationColList.Add(i);
- }
- break;
- case excelTypeRow:
- //数据类型行
- excelMediumData.propertyTypeArray = datas;
- break;
- default:
- //数据内容行
- excelMediumData.allRowItemList.Add(datas);
- //注释行号
- if(string.IsNullOrEmpty(datas[0]) || datas[0].StartsWith(annotationSign))
- excelMediumData.annotationRowList.Add(excelMediumData.allRowItemList.Count - 1);
- break;
- }
- //
- curRowIndex++;
- }
-
- if(CheckExcelMediumData(ref excelMediumData))
- {
- Debug.Log("读取Excel成功");
- return excelMediumData;
- }
- else
- {
- Debug.LogError("读取Excel失败");
- return null;
- }
- }
-
- //校验Excel数据
- private static bool CheckExcelMediumData(ref ExcelMediumData mediumData)
- {
- if(mediumData == null)
- return false;
-
- //检查数据有效性
-
- if(!mediumData.isValid)
- {
- Debug.LogError("Excel被标记无效");
- return false;
- }
-
- if(string.IsNullOrEmpty(mediumData.excelName))
- {
- Debug.LogError("Excel名字为空");
- return false;
- }
-
- if(mediumData.propertyNameArray == null || mediumData.propertyNameArray.Length == 0)
- {
- Debug.LogError("未解析到数据名称");
- return false;
- }
- if(mediumData.propertyTypeArray == null || mediumData.propertyTypeArray.Length == 0)
- {
- Debug.LogError("未解析到数据类型");
- return false;
- }
- if(mediumData.propertyNameArray.Length != mediumData.propertyTypeArray.Length)
- {
- Debug.LogError("数据名称与数据类型数量不一致");
- return false;
- }
- if(mediumData.allRowItemList.Count == 0)
- {
- Debug.LogError("数据内容为空");
- return false;
- }
-
- if(mediumData.propertyNameArray[0] != "id")
- {
- Debug.LogError("第一个字段必须是id字段");
- return false;
- }
-
- return true;
- }
-
- #endregion
-
- }
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using System.Text;
- using System.Linq;
- using System;
-
- public class ExcelCodeCreater
- {
-
- //创建代码,生成数据C#类
- public static string CreateCodeStrByExcelData(ExcelMediumData excelMediumData)
- {
- if(excelMediumData == null)
- return null;
-
- //行数据类名
- string itemClassName = excelMediumData.excelName + "ExcelItem";
- //整体数据类名
- string dataClassName = excelMediumData.excelName + "ExcelData";
-
- //开始生成类
- StringBuilder classSource = new StringBuilder();
- classSource.AppendLine("/*Auto Create, Don't Edit !!!*/");
- classSource.AppendLine();
- //添加引用
- classSource.AppendLine("using UnityEngine;");
- classSource.AppendLine("using System.Collections.Generic;");
- classSource.AppendLine("using System;");
- classSource.AppendLine("using System.IO;");
- classSource.AppendLine();
- //生成CSharp数据类
- if(excelMediumData.isCreateCSharp)
- {
- //生成行数据类,记录每行数据
- classSource.AppendLine(CreateExcelRowItemClass(itemClassName,excelMediumData));
- classSource.AppendLine();
- //生成整体数据类,记录整个Excel的所有行数据
- classSource.AppendLine(CreateExcelAllDataClass(dataClassName,itemClassName,excelMediumData));
- classSource.AppendLine();
- }
- //生成Asset创建类
- if(excelMediumData.isCreateAssignment)
- {
- //生成Asset操作类,用于自动创建Excel对应的Asset文件并赋值
- classSource.AppendLine(CreateExcelAssetClass(excelMediumData));
- classSource.AppendLine();
- }
- //
- return classSource.ToString();
- }
-
- //----------
-
- //生成行数据类
- private static string CreateExcelRowItemClass(string itemClassName,ExcelMediumData excelMediumData)
- {
- //生成Excel行数据类
- StringBuilder classSource = new StringBuilder();
- //类名
- classSource.AppendLine("[Serializable]");
- classSource.AppendLine($"public class {itemClassName} : ExcelItemBase");
- classSource.AppendLine("{");
- //声明所有字段
- for(int i = 0; i < excelMediumData.propertyNameArray.Length; i++)
- {
- //跳过注释字段
- if(excelMediumData.annotationColList.Contains(i))
- continue;
-
- //添加注释
- if(i < excelMediumData.propertyNodeArray.Length)
- {
- string propertyNode = excelMediumData.propertyNodeArray[i];
- if(!string.IsNullOrEmpty(propertyNode))
- {
- classSource.AppendLine("\t/// <summary>");
- classSource.AppendLine($"\t/// {propertyNode}");
- classSource.AppendLine("\t/// </summary>>");
- }
- }
-
- //声明行数据类的字段
- string propertyName = excelMediumData.propertyNameArray[i];
- string propertyType = excelMediumData.propertyTypeArray[i];
- string typeStr = GetPropertyType(propertyType);
- classSource.AppendLine($"\tpublic {typeStr} {propertyName};");
- }
- classSource.AppendLine("}");
- return classSource.ToString();
- }
-
- //----------
-
- //生成整体数据类
- private static string CreateExcelAllDataClass(string dataClassName,string itemClassName,ExcelMediumData excelMediumData)
- {
- StringBuilder classSource = new StringBuilder();
- //类名
- classSource.AppendLine($"public class {dataClassName} : ExcelDataBase<{itemClassName}>");
- classSource.AppendLine("{");
- //声明字段,行数据类数组
- classSource.AppendLine($"\tpublic {itemClassName}[] items;");
- classSource.AppendLine();
- //id字段类型
- string idTypeStr = GetPropertyType(excelMediumData.propertyTypeArray[0]);
- //声明字典
- classSource.AppendLine($"\tpublic Dictionary<{idTypeStr},{itemClassName}> itemDic = new Dictionary<{idTypeStr},{itemClassName}>();");
- classSource.AppendLine();
- //字段初始化方法
- classSource.AppendLine("\tpublic void Init()");
- classSource.AppendLine("\t{");
- classSource.AppendLine("\t\titemDic.Clear();");
- classSource.AppendLine("\t\tif(items != null && items.Length > 0)");
- classSource.AppendLine("\t\t{");
- classSource.AppendLine("\t\t\tfor(int i = 0; i < items.Length; i++)");
- classSource.AppendLine("\t\t\t{");
- classSource.AppendLine("\t\t\t\titemDic.Add(items[i].id, items[i]);");
- classSource.AppendLine("\t\t\t}");
- classSource.AppendLine("\t\t}");
- classSource.AppendLine("\t}");
- classSource.AppendLine();
- //字典获取方法
- classSource.AppendLine($"\tpublic {itemClassName} Get{itemClassName}({idTypeStr} id)");
- classSource.AppendLine("\t{");
- classSource.AppendLine("\t\tif(itemDic.ContainsKey(id))");
- classSource.AppendLine("\t\t\treturn itemDic[id];");
- classSource.AppendLine("\t\telse");
- classSource.AppendLine("\t\t\treturn null;");
- classSource.AppendLine("\t}");
-
- //每个字段Get函数
- classSource.AppendLine("\t#region --- Get Method ---");
- classSource.AppendLine();
-
- for(int i = 1; i < excelMediumData.propertyNameArray.Length; i++)
- {
- if(excelMediumData.annotationColList.Contains(i))
- continue;
- string propertyName = excelMediumData.propertyNameArray[i];
- string propertyType = excelMediumData.propertyTypeArray[i];
- //每个字段Get函数
- classSource.AppendLine(CreateCodePropertyMethod(itemClassName,idTypeStr,propertyName,propertyType));
- }
- classSource.AppendLine("\t#endregion");
- classSource.AppendLine("}");
- return classSource.ToString();
- }
-
- //生成数据字段对应Get方法
- private static string CreateCodePropertyMethod(string itemClassName,string idTypeStr,string propertyName,string propertyType)
- {
- StringBuilder methodBuilder = new StringBuilder();
- string itemNameStr = propertyName.FirstOrDefault().ToString().ToUpper() + propertyName.Substring(1);
- string itemTypeStr = GetPropertyType(propertyType);
- //字段Get函数
- methodBuilder.AppendLine($"\tpublic {itemTypeStr} Get{itemNameStr}({idTypeStr} id)");
- methodBuilder.AppendLine("\t{");
- methodBuilder.AppendLine($"\t\tvar item = Get{itemClassName}(id);");
- methodBuilder.AppendLine("\t\tif(item == null)");
- methodBuilder.AppendLine("\t\t\treturn default;");
- methodBuilder.AppendLine($"\t\treturn item.{propertyName};");
- methodBuilder.AppendLine("\t}");
- //如果是一维数组
- if(propertyType.Contains("[]"))
- {
- //typeStr:int[]或IntArr[] ,返回值:int或IntArr
- //string itemTypeStr1d = GetPropertyType(propertyType.Replace("[]",""));
- string itemTypeStr1d = itemTypeStr.Replace("[]","");
- methodBuilder.AppendLine($"\tpublic {itemTypeStr1d} Get{itemNameStr}({idTypeStr} id, int index)");
- methodBuilder.AppendLine("\t{");
- methodBuilder.AppendLine($"\t\tvar item0 = Get{itemClassName} (id);");
- methodBuilder.AppendLine("\t\tif(item0 == null)");
- methodBuilder.AppendLine("\t\t\treturn default;");
- methodBuilder.AppendLine($"\t\tvar item1 = item0.{propertyName};");
- methodBuilder.AppendLine("\t\tif(item1 == null || index < 0 || index >= item1.Length)");
- methodBuilder.AppendLine("\t\t\treturn default;");
- methodBuilder.AppendLine("\t\treturn item1[index];");
- methodBuilder.AppendLine("\t}");
- }
- //如果是二维数组
- if(propertyType.Contains("[][]"))
- {
- //propertyType:int[][], 返回值:int
- string itemTypeStr1d = GetPropertyType(propertyType.Replace("[][]",""));
- methodBuilder.AppendLine($"\tpublic {itemTypeStr1d} Get{itemNameStr}({idTypeStr} id, int index1, int index2)");
- methodBuilder.AppendLine("\t{");
- methodBuilder.AppendLine($"\t\tvar item0 = Get{itemClassName}(id);");
- methodBuilder.AppendLine("\t\tif(item0 == null)");
- methodBuilder.AppendLine("\t\t\treturn default;");
- methodBuilder.AppendLine($"\t\tvar item1 = item0.{propertyName};");
- methodBuilder.AppendLine("\t\tif(item1 == null || index1 < 0 || index1 >= item1.Length)");
- methodBuilder.AppendLine("\t\t\treturn default;");
- methodBuilder.AppendLine("\t\tvar item2 = item1[index1];");
- methodBuilder.AppendLine("\t\tif(item2.array == null || index2 < 0 || index2 >= item2.array.Length)");
- methodBuilder.AppendLine("\t\t\treturn default;");
- methodBuilder.AppendLine("\t\treturn item2.array[index2];");
- methodBuilder.AppendLine("\t}");
- }
- //
- return methodBuilder.ToString();
- }
-
- //----------
-
- //生成Asset创建类
- private static string CreateExcelAssetClass(ExcelMediumData excelMediumData)
- {
- string itemClassName = excelMediumData.excelName + "ExcelItem";
- string dataClassName = excelMediumData.excelName + "ExcelData";
- string assignmentClassName = excelMediumData.excelName + "AssetAssignment";
-
- StringBuilder classSource = new StringBuilder();
- classSource.AppendLine("#if UNITY_EDITOR");
- //类名
- classSource.AppendLine($"public class {assignmentClassName}");
- classSource.AppendLine("{");
- //方法名
- classSource.AppendLine("\tpublic static bool CreateAsset(ExcelMediumData excelMediumData, string excelAssetPath)");
- //方法体,若有需要可加入try/catch
- classSource.AppendLine("\t{");
- classSource.AppendLine("\t\tvar allRowItemDicList = excelMediumData.GetAllRowItemDicList();");
- classSource.AppendLine("\t\tif(allRowItemDicList == null || allRowItemDicList.Count == 0)");
- classSource.AppendLine("\t\t\treturn false;");
- classSource.AppendLine();
- classSource.AppendLine("\t\tint rowCount = allRowItemDicList.Count;");
- classSource.AppendLine($"\t\t{dataClassName} excelDataAsset = ScriptableObject.CreateInstance<{dataClassName}>();");
- classSource.AppendLine($"\t\texcelDataAsset.items = new {itemClassName}[rowCount];");
- classSource.AppendLine();
- classSource.AppendLine("\t\tfor(int i = 0; i < rowCount; i++)");
- classSource.AppendLine("\t\t{");
- classSource.AppendLine("\t\t\tvar itemRowDic = allRowItemDicList[i];");
- classSource.AppendLine($"\t\t\texcelDataAsset.items[i] = new {itemClassName}();");
-
- for(int i = 0; i < excelMediumData.propertyNameArray.Length; i++)
- {
- if(excelMediumData.annotationColList.Contains(i))
- continue;
- string propertyName = excelMediumData.propertyNameArray[i];
- string propertyType = excelMediumData.propertyTypeArray[i];
- classSource.Append($"\t\t\texcelDataAsset.items[i].{propertyName} = ");
- classSource.Append(AssignmentCodeProperty(propertyName,propertyType));
- classSource.AppendLine(";");
- }
- classSource.AppendLine("\t\t}");
- classSource.AppendLine("\t\tif(!Directory.Exists(excelAssetPath))");
- classSource.AppendLine("\t\t\tDirectory.CreateDirectory(excelAssetPath);");
- classSource.AppendLine($"\t\tstring fullPath = Path.Combine(excelAssetPath,typeof({dataClassName}).Name) + \".asset\";");
- classSource.AppendLine("\t\tUnityEditor.AssetDatabase.DeleteAsset(fullPath);");
- classSource.AppendLine("\t\tUnityEditor.AssetDatabase.CreateAsset(excelDataAsset,fullPath);");
- classSource.AppendLine("\t\tUnityEditor.AssetDatabase.Refresh();");
- classSource.AppendLine("\t\treturn true;");
- classSource.AppendLine("\t}");
- //
- classSource.AppendLine("}");
- classSource.AppendLine("#endif");
- return classSource.ToString();
- }
-
- //声明Asset操作类字段
- private static string AssignmentCodeProperty(string propertyName,string propertyType)
- {
- string stringValue = $"itemRowDic[\"{propertyName}\"]";
- string typeStr = GetPropertyType(propertyType);
- switch(typeStr)
- {
- //字段
- case "int":
- return "StringUtility.StringToInt(" + stringValue + ")";
- case "float":
- return "StringUtility.StringToFloat(" + stringValue + ")";
- case "bool":
- return "StringUtility.StringToBool(" + stringValue + ")";
- case "Vector2":
- return "StringUtility.StringToVector2(" + stringValue + ")";
- case "Vector3":
- return "StringUtility.StringToVector3(" + stringValue + ")";
- case "Vector2Int":
- return "StringUtility.StringToVector2Int(" + stringValue + ")";
- case "Vector3Int":
- return "StringUtility.StringToVector3Int(" + stringValue + ")";
- case "Color":
- return "StringUtility.StringToColor(" + stringValue + ")";
- case "Color32":
- return "StringUtility.StringToColor32(" + stringValue + ")";
- case "string":
- return stringValue;
- //一维
- case "int[]":
- return "StringUtility.StringToIntArray(" + stringValue + ")";
- case "float[]":
- return "StringUtility.StringToFloatArray(" + stringValue + ")";
- case "bool[]":
- return "StringUtility.StringToBoolArray(" + stringValue + ")";
- case "Vector2[]":
- return "StringUtility.StringToVector2Array(" + stringValue + ")";
- case "Vector3[]":
- return "StringUtility.StringToVector3Array(" + stringValue + ")";
- case "Vector2Int[]":
- return "StringUtility.StringToVector2IntArray(" + stringValue + ")";
- case "Vector3Int[]":
- return "StringUtility.StringToVector3IntArray(" + stringValue + ")";
- case "Color[]":
- return "StringUtility.StringToColorArray(" + stringValue + ")";
- case "Color32[]":
- return "StringUtility.StringToColor32Array(" + stringValue + ")";
- case "string[]":
- return "StringUtility.StringToStringArray(" + stringValue + ")";
- //二维
- case "IntArr[]":
- return "StringUtility.StringToIntArray2D(" + stringValue + ")";
- case "FloatArr[]":
- return "StringUtility.StringToFloatArray2D(" + stringValue + ")";
- case "BoolArr[]":
- return "StringUtility.StringToBoolArray2D(" + stringValue + ")";
- case "Vector2Arr[]":
- return "StringUtility.StringToVector2Array2D(" + stringValue + ")";
- case "Vector3Arr[]":
- return "StringUtility.StringToVector3Array2D(" + stringValue + ")";
- case "Vector2IntArr[]":
- return "StringUtility.StringToVector2IntArray2D(" + stringValue + ")";
- case "Vector3IntArr[]":
- return "StringUtility.StringToVector3IntArray2D(" + stringValue + ")";
- case "ColorArr[]":
- return "StringUtility.StringToColorArray2D(" + stringValue + ")";
- case "Color32Arr[]":
- return "StringUtility.StringToColor32Array2D(" + stringValue + ")";
- case "StringArr[]":
- return "StringUtility.StringToStringArray2D(" + stringValue + ")";
- default:
- //枚举
- if(propertyType.StartsWith("enum"))
- {
- string enumType = propertyType.Split('|').FirstOrDefault();
- string enumName = propertyType.Split('|').LastOrDefault();
- if(enumType == "enum")
- return "StringUtility.StringToEnum<" + enumName + ">(" + stringValue + ")";
- else if(enumType == "enum[]")
- return "StringUtility.StringToEnumArray<" + enumName + ">(" + stringValue + ")";
- else if(enumType == "enum[][]")
- return "StringUtility.StringToEnumArray2D<" + enumName + ">(" + stringValue + ")";
- }
- return stringValue;
- }
- }
-
- //判断字段类型
- private static string GetPropertyType(string propertyType)
- {
- string lowerType = propertyType.ToLower();
- switch(lowerType)
- {
- case "int":
- return "int";
- case "int[]":
- return "int[]";
- case "int[][]":
- return "IntArr[]";
- case "float":
- return "float";
- case "float[]":
- return "float[]";
- case "float[][]":
- return "FloatArr[]";
- case "bool":
- return "bool";
- case "bool[]":
- return "bool[]";
- case "bool[][]":
- return "BoolArr[]";
- case "string":
- return "string";
- case "string[]":
- return "string[]";
- case "string[][]":
- return "StringArr[]";
-
- case "vector2":
- return "Vector2";
- case "vector2[]":
- return "Vector2[]";
- case "vector2[][]":
- return "Vector2Arr[]";
- case "vector2int":
- return "Vector2Int";
- case "vector2int[]":
- return "Vector2Int[]";
- case "vector2int[][]":
- return "Vector2IntArr[]";
-
- case "vector3":
- return "Vector3";
- case "vector3[]":
- return "Vector3[]";
- case "vector3[][]":
- return "Vector3Arr[]";
- case "vector3int":
- return "Vector3Int";
- case "vector3int[]":
- return "Vector3Int[]";
- case "vector3int[][]":
- return "Vector3IntArr[]";
-
- case "color":
- return "Color";
- case "color[]":
- return "Color[]";
- case "color[][]":
- return "ColorArr[]";
- case "color32":
- return "Color32";
- case "color32[]":
- return "Color32[]";
- case "color32[][]":
- return "Color32Arr[]";
-
- default:
- if(propertyType.StartsWith("enum"))
- {
- string enumType = propertyType.Split('|').FirstOrDefault();
- string enumName = propertyType.Split('|').LastOrDefault();
- switch(enumType)
- {
- case "enum":
- return enumName;
- case "enum[]":
- return $"{enumName}[]";
- case "enum[][]":
- return $"EnumArr<{enumName}>[]";
- default:
- break;
- }
- }
- return "string";
- }
- }
-
- }
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- //Excel中间数据
- public class ExcelMediumData
- {
- //Excel名字
- public string excelName;
-
- //Excel是否有效
- public bool isValid = false;
- //是否生成CSharp数据类
- public bool isCreateCSharp = false;
- //是否生成Asset创建类
- public bool isCreateAssignment = false;
- //是否生成Asset文件
- public bool isCreateAsset = false;
-
- //数据注释
- public string[] propertyNodeArray = null;
- //数据名称
- public string[] propertyNameArray = null;
- //数据类型
- public string[] propertyTypeArray = null;
- //List<每行数据内容>
- public List<string[]> allRowItemList = new List<string[]>();
-
- //注释行号
- public List<int> annotationRowList = new List<int>();
- //注释列号
- public List<int> annotationColList = new List<int>();
-
- //List<每行数据>,List<Dictionary<单元格字段名称, 单元格字段值>>
- public List<Dictionary<string,string>> GetAllRowItemDicList()
- {
- if(propertyNameArray == null || propertyNameArray.Length == 0)
- return null;
- if(allRowItemList.Count == 0)
- return null;
-
- List<Dictionary<string,string>> allRowItemDicList = new List<Dictionary<string,string>>(allRowItemList.Count);
-
- for(int i = 0; i < allRowItemList.Count; i++)
- {
- string[] rowArray = allRowItemList[i];
- //跳过空数据
- if(rowArray == null || rowArray.Length == 0)
- continue;
- //跳过注释数据
- if(annotationRowList.Contains(i))
- continue;
-
- //每行数据,对应字段名称和字段值
- Dictionary<string,string> rowDic = new Dictionary<string,string>();
- for(int j = 0; j < propertyNameArray.Length; j++)
- {
- //跳过注释字段
- if(annotationColList.Contains(j))
- continue;
-
- string propertyName = propertyNameArray[j];
- string propertyValue = j < rowArray.Length ? rowArray[j] : null;
- rowDic[propertyName] = propertyValue;
- }
- allRowItemDicList.Add(rowDic);
- }
- return allRowItemDicList;
- }
-
- }
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using System.Linq;
- using System;
-
- public class ExcelDataBase<T> : ScriptableObject where T : ExcelItemBase
- {
-
- }
-
- public class ExcelItemBase
- {
-
- }
-
-
- [Serializable]
- public struct StringArr
- {
- public string[] array;
- }
- [Serializable]
- public struct IntArr
- {
- public int[] array;
- }
- [Serializable]
- public struct FloatArr
- {
- public float[] array;
- }
- [Serializable]
- public struct BoolArr
- {
- public bool[] array;
- }
-
- [Serializable]
- public struct Vector2Arr
- {
- public Vector2[] array;
- }
- [Serializable]
- public struct Vector3Arr
- {
- public Vector3[] array;
- }
- [Serializable]
- public struct Vector2IntArr
- {
- public Vector2Int[] array;
- }
- [Serializable]
- public struct Vector3IntArr
- {
- public Vector3Int[] array;
- }
- [Serializable]
- public struct ColorArr
- {
- public Color[] array;
- }
- [Serializable]
- public struct Color32Arr
- {
- public Color32[] array;
- }
-
- 不支持泛型枚举序列化
- //[Serializable]
- //public struct EnumArr<T> where T : Enum
- //{
- // public T[] array;
- //}
-
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using System.Text.RegularExpressions;
- using System;
- using System.Text;
- using System.Linq;
- using System.Runtime.CompilerServices;
-
- public static class StringUtility
- {
-
- #region --- AddColor ---
-
- public static string AddColor(object obj,Color color)
- {
- return AddColor(obj,color);
- }
- public static string AddColor(this string str,Color color)
- {
- //把颜色转换为16进制字符串,添加到富文本
- return string.Format("<color=#{0}>{1}</color>",ColorUtility.ToHtmlStringRGBA(color),str);
- }
- public static string AddColor(string str1,string str2,Color color)
- {
- return AddColor(str1 + str2,color);
- }
- public static string AddColor(string str1,string str2,string str3,Color color)
- {
- return AddColor(str1 + str2 + str3,color);
- }
-
- #endregion
-
- #region --- string length ---
-
- /// <summary>
- /// 化简字符串长度
- /// </summary>
- /// <param name="targetStr"></param>
- /// <param name="targetLength">目标长度,英文字符==1,中文字符==2</param>
- /// <returns></returns>
- public static string AbbrevStringWithinLength(string targetStr,int targetLength,string abbrevPostfix)
- {
- //C#实际统计:一个中文字符长度==1,英文字符长度==1
- //UI显示要求:一个中文字符长度==2,英文字符长度==1
-
- //校验参数
- if(string.IsNullOrEmpty(targetStr) || targetLength <= 0)
- return targetStr;
- //字符串长度 * 2 <= 目标长度,即使是全中文也在长度范围内
- if(targetStr.Length * 2 <= targetLength)
- return targetStr;
- //遍历字符
- char[] chars = targetStr.ToCharArray();
- int curLen = 0;
- for(int i = 0; i < chars.Length; i++)
- {
- //累加字符串长度
- if(chars[i] >= 0x4e00 && chars[i] <= 0x9fbb)
- curLen += 2;
- else
- curLen += 1;
-
- //如果当前位置累计长度超过目标长度,取0~i-1,即Substring(0,i)
- if(curLen > targetLength)
- return targetStr.Substring(0,i) + abbrevPostfix;
- }
- return targetStr;
- }
-
- #endregion
-
- #region --- String To Array ---
-
- //string
-
- public static byte StringToByte(string valueStr)
- {
- byte value;
- if(byte.TryParse(valueStr,out value))
- return value;
- else
- return 0;
- }
-
- public static string[] StringToStringArray(string valueStr,char splitSign = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
- return valueStr.Split(splitSign);
- }
-
- public static StringArr[] StringToStringArray2D(string valueStr,char splitSign1 = '&',char splitSign2 = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
- string[] strArr1 = valueStr.Split(splitSign1);
- if(strArr1.Length == 0)
- return null;
-
- StringArr[] arrArr = new StringArr[strArr1.Length];
- for(int i = 0; i < strArr1.Length; i++)
- {
- arrArr[i] = new StringArr()
- {
- array = strArr1[i].Split(splitSign2)
- };
-
- }
- return arrArr;
- }
-
- //int
-
- public static int StringToInt(string valueStr)
- {
- int value;
- if(int.TryParse(valueStr,out value))
- return value;
- else
- return 0;
- }
-
- public static int[] StringToIntArray(string valueStr,char splitSign = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
-
- string[] valueArr = valueStr.Split(splitSign);
- if(valueArr == null || valueArr.Length == 0)
- return null;
-
- int[] intArr = new int[valueArr.Length];
- for(int i = 0; i < valueArr.Length; i++)
- {
- intArr[i] = StringToInt(valueArr[i]);
- }
- return intArr;
- }
-
- public static IntArr[] StringToIntArray2D(string valueStr,char splitSign1 = '&',char splitSign2 = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
- string[] strArr1 = valueStr.Split(splitSign1);
- if(strArr1.Length == 0)
- return null;
-
- IntArr[] arrArr = new IntArr[strArr1.Length];
- for(int i = 0; i < strArr1.Length; i++)
- {
- arrArr[i] = new IntArr()
- {
- array = StringToIntArray(strArr1[i],splitSign2)
- };
-
- }
- return arrArr;
- }
-
- //float
-
- public static float StringToFloat(string valueStr)
- {
- float value;
- if(float.TryParse(valueStr,out value))
- return value;
- else
- return 0;
- }
-
- public static float[] StringToFloatArray(string valueStr,char splitSign = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
-
- string[] valueArr = valueStr.Split(splitSign);
- if(valueArr == null || valueArr.Length == 0)
- return null;
-
- float[] floatArr = new float[valueArr.Length];
- for(int i = 0; i < valueArr.Length; i++)
- {
- floatArr[i] = StringToFloat(valueArr[i]);
- }
- return floatArr;
- }
-
- public static FloatArr[] StringToFloatArray2D(string valueStr,char splitSign1 = '&',char splitSign2 = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
- string[] strArr1 = valueStr.Split(splitSign1);
- if(strArr1.Length == 0)
- return null;
-
- FloatArr[] arrArr = new FloatArr[strArr1.Length];
- for(int i = 0; i < strArr1.Length; i++)
- {
- arrArr[i] = new FloatArr()
- {
- array = StringToFloatArray(strArr1[i],splitSign2)
- };
-
- }
- return arrArr;
- }
-
- //bool
-
- public static bool StringToBool(string valueStr)
- {
- bool value;
- if(bool.TryParse(valueStr,out value))
- return value;
- else
- return false;
- }
-
- public static bool[] StringToBoolArray(string valueStr,char splitSign = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
-
- string[] valueArr = valueStr.Split(splitSign);
- if(valueArr == null || valueArr.Length == 0)
- return null;
-
- bool[] boolArr = new bool[valueArr.Length];
- for(int i = 0; i < valueArr.Length; i++)
- {
- boolArr[i] = StringToBool(valueArr[i]);
- }
- return boolArr;
- }
-
- public static BoolArr[] StringToBoolArray2D(string valueStr,char splitSign1 = '&',char splitSign2 = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
- string[] strArr1 = valueStr.Split(splitSign1);
- if(strArr1.Length == 0)
- return null;
-
- BoolArr[] arrArr = new BoolArr[strArr1.Length];
- for(int i = 0; i < strArr1.Length; i++)
- {
- arrArr[i] = new BoolArr()
- {
- array = StringToBoolArray(strArr1[i],splitSign2)
- };
-
- }
- return arrArr;
- }
-
- //enum
-
- public static T StringToEnum<T>(string valueStr) where T : Enum
- {
- if(string.IsNullOrEmpty(valueStr))
- return (T)default;
-
- //先校验字符串是否为枚举值
- int intValue;
- if(int.TryParse(valueStr,out intValue))
- {
- if(Enum.IsDefined(typeof(T),intValue))
- return (T)Enum.ToObject(typeof(T),intValue);
- }
- //如果不是枚举值,当做枚举名处理
- try
- {
- T t = (T)Enum.Parse(typeof(T),valueStr);
- if(Enum.IsDefined(typeof(T),t))
- return t;
- }
- catch(Exception e)
- {
- Debug.LogError(e);
- }
- Debug.LogError(string.Format("解析枚举错误 {0} : {1}",typeof(T),valueStr));
- return (T)default;
- }
-
- public static T[] StringToEnumArray<T>(string valueStr,char splitSign = '|') where T : Enum
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
-
- string[] valueArr = valueStr.Split(splitSign);
- if(valueArr == null || valueArr.Length == 0)
- return null;
-
- T[] enumArr = new T[valueArr.Length];
- for(int i = 0; i < valueArr.Length; i++)
- {
- enumArr[i] = StringToEnum<T>(valueArr[i]);
- }
- return enumArr;
- }
-
- 不支持泛型枚举序列化
- //public static EnumArr<T>[] StringToEnumArray2D<T>(string valueStr,char splitSign1 = '&',char splitSign2 = '|') where T : Enum
- //{
- // if(string.IsNullOrEmpty(valueStr))
- // return null;
- // string[] strArr1 = valueStr.Split(splitSign1);
- // if(strArr1.Length == 0)
- // return null;
-
- // EnumArr<T>[] arrArr = new EnumArr<T>[strArr1.Length];
- // for(int i = 0; i < strArr1.Length; i++)
- // {
- // arrArr[i] = new EnumArr<T>()
- // {
- // array = StringToEnumArray<T>(strArr1[i],splitSign2)
- // };
-
- // }
- // return arrArr;
- //}
-
- //vector2
-
- public static Vector2 StringToVector2(string valueStr,char splitSign = ',')
- {
- Vector2 value = Vector2.zero;
- if(!string.IsNullOrEmpty(valueStr))
- {
- string[] stringArray = valueStr.Split(splitSign);
- if(stringArray != null && stringArray.Length >= 2)
- {
- value.x = StringToFloat(stringArray[0]);
- value.y = StringToFloat(stringArray[1]);
- return value;
- }
- }
- Debug.LogWarning("String to Vector2 error");
- return value;
- }
-
- public static Vector2[] StringToVector2Array(string valueStr,char splitSign = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
-
- string[] stringArray = valueStr.Split(splitSign);
- if(stringArray == null || stringArray.Length == 0)
- return null;
-
- Vector2[] vector2s = new Vector2[stringArray.Length];
- for(int i = 0; i < stringArray.Length; i++)
- {
- vector2s[i] = StringToVector2(stringArray[i]);
- }
- return vector2s;
- }
-
- public static Vector2Arr[] StringToVector2Array2D(string valueStr,char splitSign1 = '&',char splitSign2 = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
- string[] strArr1 = valueStr.Split(splitSign1);
- if(strArr1.Length == 0)
- return null;
-
- Vector2Arr[] arrArr = new Vector2Arr[strArr1.Length];
- for(int i = 0; i < strArr1.Length; i++)
- {
- arrArr[i] = new Vector2Arr()
- {
- array = StringToVector2Array(strArr1[i],splitSign2)
- };
- }
- return arrArr;
- }
-
- //vector3
-
- public static Vector3 StringToVector3(string valueStr,char splitSign = ',')
- {
- Vector3 value = Vector3.zero;
- if(!string.IsNullOrEmpty(valueStr))
- {
- string[] stringArray = valueStr.Split(splitSign);
- if(stringArray.Length >= 3)
- {
- value.x = StringToFloat(stringArray[0]);
- value.y = StringToFloat(stringArray[1]);
- value.z = StringToFloat(stringArray[2]);
- return value;
- }
- }
- Debug.LogWarning("String to Vector3 error");
- return value;
- }
-
- public static Vector3[] StringToVector3Array(string valueStr,char splitSign = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
-
- string[] stringArray = valueStr.Split(splitSign);
- if(stringArray == null || stringArray.Length == 0)
- return null;
-
- Vector3[] vector3s = new Vector3[stringArray.Length];
- for(int i = 0; i < stringArray.Length; i++)
- {
- vector3s[i] = StringToVector3(stringArray[i]);
- }
- return vector3s;
- }
-
- public static Vector3Arr[] StringToVector3Array2D(string valueStr,char splitSign1 = '&',char splitSign2 = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
- string[] strArr1 = valueStr.Split(splitSign1);
- if(strArr1.Length == 0)
- return null;
-
- Vector3Arr[] arrArr = new Vector3Arr[strArr1.Length];
- for(int i = 0; i < strArr1.Length; i++)
- {
- arrArr[i] = new Vector3Arr()
- {
- array = StringToVector3Array(strArr1[i],splitSign2)
- };
- }
- return arrArr;
- }
-
- //vector2Int
-
- public static Vector2Int StringToVector2Int(string valueStr,char splitSign = ',')
- {
- Vector2Int value = Vector2Int.zero;
- if(!string.IsNullOrEmpty(valueStr))
- {
- string[] stringArray = valueStr.Split(splitSign);
- if(stringArray != null && stringArray.Length >= 2)
- {
- value.x = StringToInt(stringArray[0]);
- value.y = StringToInt(stringArray[1]);
- return value;
- }
- }
- Debug.LogWarning("String to Vector2Int error");
- return value;
- }
-
- public static Vector2Int[] StringToVector2IntArray(string valueStr,char splitSign = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
-
- string[] stringArray = valueStr.Split(splitSign);
- if(stringArray == null || stringArray.Length == 0)
- return null;
-
- Vector2Int[] vector2Ints = new Vector2Int[stringArray.Length];
- for(int i = 0; i < stringArray.Length; i++)
- {
- vector2Ints[i] = StringToVector2Int(stringArray[i]);
- }
- return vector2Ints;
- }
-
- public static Vector2IntArr[] StringToVector2IntArray2D(string valueStr,char splitSign1 = '&',char splitSign2 = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
- string[] strArr1 = valueStr.Split(splitSign1);
- if(strArr1.Length == 0)
- return null;
-
- Vector2IntArr[] arrArr = new Vector2IntArr[strArr1.Length];
- for(int i = 0; i < strArr1.Length; i++)
- {
- arrArr[i] = new Vector2IntArr()
- {
- array = StringToVector2IntArray(strArr1[i],splitSign2)
- };
- }
- return arrArr;
- }
-
- //vector3Int
-
- public static Vector3Int StringToVector3Int(string valueStr,char splitSign = ',')
- {
- Vector3Int value = Vector3Int.zero;
- if(!string.IsNullOrEmpty(valueStr))
- {
- string[] stringArray = valueStr.Split(splitSign);
- if(stringArray.Length >= 3)
- {
- value.x = StringToInt(stringArray[0]);
- value.y = StringToInt(stringArray[1]);
- value.z = StringToInt(stringArray[2]);
- return value;
- }
- }
- Debug.LogWarning("String to Vector3 error");
- return value;
- }
-
- public static Vector3Int[] StringToVector3IntArray(string valueStr,char splitSign = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
-
- string[] stringArray = valueStr.Split(splitSign);
- if(stringArray == null || stringArray.Length == 0)
- return null;
-
- Vector3Int[] vector3Ints = new Vector3Int[stringArray.Length];
- for(int i = 0; i < stringArray.Length; i++)
- {
- vector3Ints[i] = StringToVector3Int(stringArray[i]);
- }
- return vector3Ints;
- }
-
- public static Vector3IntArr[] StringToVector3IntArray2D(string valueStr,char splitSign1 = '&',char splitSign2 = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
- string[] strArr1 = valueStr.Split(splitSign1);
- if(strArr1.Length == 0)
- return null;
-
- Vector3IntArr[] arrArr = new Vector3IntArr[strArr1.Length];
- for(int i = 0; i < strArr1.Length; i++)
- {
- arrArr[i] = new Vector3IntArr()
- {
- array = StringToVector3IntArray(strArr1[i],splitSign2)
- };
- }
- return arrArr;
- }
-
- //color
-
- public static Color StringToColor(string valueStr,char splitSign = ',')
- {
- if(string.IsNullOrEmpty(valueStr))
- return Color.white;
-
- string[] stringArray = valueStr.Split(splitSign);
- if(stringArray.Length < 3)
- return Color.white;
-
- Color color = new Color()
- {
- r = StringToFloat(stringArray[0]),
- g = StringToFloat(stringArray[1]),
- b = StringToFloat(stringArray[2]),
- a = stringArray.Length < 4 ? 1 : StringToFloat(stringArray[3])
- };
- return color;
- }
- public static Color32 StringToColor32(string valueStr,char splitSign = ',')
- {
- if(string.IsNullOrEmpty(valueStr))
- return Color.white;
-
- string[] stringArray = valueStr.Split(splitSign);
- if(stringArray.Length < 3)
- return Color.white;
-
- Color32 color = new Color32()
- {
- r = StringToByte(stringArray[0]),
- g = StringToByte(stringArray[1]),
- b = StringToByte(stringArray[2]),
- a = stringArray.Length < 4 ? (byte)1 : StringToByte(stringArray[3])
- };
- return color;
- }
-
- public static Color[] StringToColorArray(string valueStr,char splitSign = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
-
- string[] stringArray = valueStr.Split(splitSign);
- if(stringArray == null || stringArray.Length == 0)
- return null;
-
- Color[] colors = new Color[stringArray.Length];
- for(int i = 0; i < stringArray.Length; i++)
- {
- colors[i] = StringToColor(stringArray[i]);
- }
- return colors;
- }
-
- public static Color32[] StringToColor32Array(string valueStr,char splitSign = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
-
- string[] stringArray = valueStr.Split(splitSign);
- if(stringArray == null || stringArray.Length == 0)
- return null;
-
- Color32[] colors = new Color32[stringArray.Length];
- for(int i = 0; i < stringArray.Length; i++)
- {
- colors[i] = StringToColor32(stringArray[i]);
- }
- return colors;
- }
-
- public static ColorArr[] StringToColorArray2D(string valueStr,char splitSign1 = '&',char splitSign2 = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
- string[] strArr1 = valueStr.Split(splitSign1);
- if(strArr1.Length == 0)
- return null;
-
- ColorArr[] arrArr = new ColorArr[strArr1.Length];
- for(int i = 0; i < strArr1.Length; i++)
- {
- arrArr[i] = new ColorArr()
- {
- array = StringToColorArray(strArr1[i],splitSign2)
- };
- }
- return arrArr;
- }
- public static Color32Arr[] StringToColor32Array2D(string valueStr,char splitSign1 = '&',char splitSign2 = '|')
- {
- if(string.IsNullOrEmpty(valueStr))
- return null;
- string[] strArr1 = valueStr.Split(splitSign1);
- if(strArr1.Length == 0)
- return null;
-
- Color32Arr[] arrArr = new Color32Arr[strArr1.Length];
- for(int i = 0; i < strArr1.Length; i++)
- {
- arrArr[i] = new Color32Arr()
- {
- array = StringToColor32Array(strArr1[i],splitSign2)
- };
- }
- return arrArr;
- }
-
- #endregion
-
- #region MyRegion
-
- public static string GetRandomString(int length)
- {
- StringBuilder builder = new StringBuilder();
- string abc = "abcdefghijklmnopqrstuvwxyzo0123456789QWERTYUIOPASDFGHJKLZXCCVBMN";
- for(int i = 0; i < length; i++)
- {
- builder.Append(abc[UnityEngine.Random.Range(0,abc.Length - 1)]);
- }
- return builder.ToString();
- }
-
- public static string Join<T>(T[] arr,string join = ",")
- {
- if(arr == null || arr.Length == 0)
- return null;
-
- StringBuilder builder = new StringBuilder();
- for(int i = 0; i < arr.Length; i++)
- {
- builder.Append(arr[i]);
- if(i < arr.Length - 1)
- builder.Append(join);
- }
- return builder.ToString();
- }
-
- /// <summary>
- /// 中文逗号转英文逗号
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- public static string ToDBC(string input)
- {
- char[] c = input.ToCharArray();
- for(int i = 0; i < c.Length; i++)
- {
- if(c[i] == 12288)
- {
- c[i] = (char)32;
- continue;
- }
- if(c[i] > 65280 && c[i] < 65375)
- c[i] = (char)(c[i] - 65248);
- }
- return new string(c);
- }
-
- /// <summary>
- /// 字符转 ascii 码
- /// </summary>
- /// <param name="character"></param>
- /// <returns></returns>
- public static int Asc(string character)
- {
- if(character.Length == 1)
- {
- System.Text.ASCIIEncoding asciiEncoding = new System.Text.ASCIIEncoding();
- int intAsciiCode = (int)asciiEncoding.GetBytes(character)[0];
- return (intAsciiCode);
- }
- Debug.LogError("Character is not valid.");
- return -1;
- }
-
- /// <summary>
- /// ascii码转字符
- /// </summary>
- /// <param name="asciiCode"></param>
- /// <returns></returns>
- public static string Chr(int asciiCode)
- {
- if(asciiCode >= 0 && asciiCode <= 255)
- {
- System.Text.ASCIIEncoding asciiEncoding = new System.Text.ASCIIEncoding();
- byte[] byteArray = new byte[] { (byte)asciiCode };
- string strCharacter = asciiEncoding.GetString(byteArray);
- return (strCharacter);
- }
- Debug.LogError("ASCII Code is not valid.");
- return string.Empty;
- }
-
- /// <summary>
- /// 过滤掉表情符号
- /// </summary>
- /// <returns>The emoji.</returns>
- /// <param name="str">String.</param>
- public static string FilterEmoji(string str)
- {
- List<string> patten = new List<string>() { @"\p{Cs}",@"\p{Co}",@"\p{Cn}",@"[\u2702-\u27B0]" };
- for(int i = 0; i < patten.Count; i++)
- {
- str = Regex.Replace(str,patten[i],"");//屏蔽emoji
- }
- return str;
- }
-
- /// <summary>
- /// 过滤掉表情符号
- /// </summary>
- /// <returns>The emoji.</returns>
- /// <param name="str">String.</param>
- public static bool IsFilterEmoji(string str)
- {
- bool bEmoji = false;
- List<string> patten = new List<string>() { @"\p{Cs}",@"\p{Co}",@"\p{Cn}",@"[\u2702-\u27B0]" };
- for(int i = 0; i < patten.Count; i++)
- {
- bEmoji = Regex.IsMatch(str,patten[i]);
- if(bEmoji)
- {
- break;
- }
- }
- return bEmoji;
- }
-
- #endregion
-
- #region StringObjectDictionaryExtensions
-
- /// <summary>
- /// 针对字典中包含以下键值进行结构:mctid0=xxx;mccount0=1,mctid1=kn2,mccount=2。将其前缀去掉,数字后缀变为键,如{后缀,(去掉前后缀的键,值)},注意后缀可能是空字符串即没有后缀
- /// </summary>
- /// <param name="dic"></param>
- /// <param name="prefix">前缀,可以是空引用或空字符串,都表示没有前缀。</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static IEnumerable<IGrouping<string,(string, object)>> GetValuesWithoutPrefix(this IReadOnlyDictionary<string,object> dic,string prefix = null)
- {
- //prefix ??= string.Empty;
- prefix = prefix ?? string.Empty;
-
- var coll = from tmp in dic.Where(c => c.Key.StartsWith(prefix)) //仅针对指定前缀的键值
- let p3 = tmp.Key.Get3Segment(prefix)
- group (p3.Item2, tmp.Value) by p3.Item3;
- return coll;
- }
-
- /// <summary>
- /// 分解字符串为三段,前缀,词根,数字后缀(字符串形式)。
- /// </summary>
- /// <param name="str"></param>
- /// <param name="prefix">前缀,可以是空引用或空字符串,都表示没有前缀。</param>
- /// <returns></returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static (string, string, string) Get3Segment(this string str,string prefix = null)
- {
- //prefix ??= string.Empty;
- prefix = prefix ?? string.Empty;
-
- //最后十进制数字尾串的长度
- int suffixLen = Enumerable.Reverse(str).TakeWhile(c => char.IsDigit(c)).Count();
- //获取十进制数字后缀
- //string suufix = str[^suffixLen..]; //^suffixLen:倒序下标;suffixLen..:从指定位置开始直到末尾
- string suufix = str.Substring(str.Length - suffixLen);
-
- //return (prefix, str[prefix.Length..^suufix.Length], suufix);
- string middle = str.Substring(prefix.Length,str.Length - prefix.Length - suufix.Length);
- return (prefix, middle, suufix);
- }
-
- #endregion
-
- }