在做游戏的过程中肯定需要大量的数据,不管是UI上的还是玩家身上需要的等等,获取数据比较简单的方式就是在一些表中读取嘛,很多游戏公司是把一些数据放到表中让策划去配,有的是Excel表,有的是TXT文件,还有csv等很多其他的,反正各有各的神通。因为毕设也不会用太多东西,所以简单写了一下适合自己工程的,好坏就不探究了。
参考文章:点击这里获取跟excel相关dll并先做了解 首先可以大致了解一下我想要效果:
整个逻辑可以简单地总结为:拿到一张Excel表格,自动生成一个跟表格数据相关的类,一张表对应一个cs文件,然后能在TableManager中自动生成获取表格数据的方法,对所有的Excel都执行这个操作,简简单单。
做的过程中可能会报System.Data不匹配的错误,这个可以直接导入自己unity路径下的System.Data.dll,路径:u3d\Editor\Data\Mono\lib\mono\2.0。
························································································
首先我们在工程里建一个文件夹来存放Excel表格,然后要有存放表格类的文件夹或路径,还有生成TableManager.cs文件的路径。可以个文件进行配置:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ExcelConfig
{
/// <summary>
/// 存放excel表文件夹的的路径,本例excel表放在了"Assets/Excel/"当中
/// </summary>
public static readonly string excelsFolderPath = Application.dataPath + "/Excel/";
/// <summary>
/// 存放表格对应类的cs文件路径
/// </summary>
public static readonly string TableClassPath = "Assets/Game/Script/TableScript/";
/// <summary>
/// 存放TableManager的文件夹路径
/// </summary>
public static readonly string TableManagerPath = "Assets/Game/Script/TableRead/";
}
表格后缀类型是“.xlsx”,里面的内容是这样的:
最终效果可以先了解一下,我们在unity中点击工具:
后面如果不需要增加表格或增加表格的列的话就不需要再使用工具了,接下来可以写个按钮事件来测试效果:
public void onclick()
{
int id = 1;
Tab_Tasks tasks = TableManager.GetTasksById(id);
if (tasks == null)
{
return;
}
Debug.Log("===" + tasks.Id + "===" + tasks.Name + "===" + tasks.Text);
Debug.Log("===" + tasks.Scene + "===" + tasks.Passed);
}
效果:
fine开搞,首先要拿到表格名字并生成相应的类,类中的成员变量要根据表格内容自动生成,那么首先得拿到每个表格路径,我们可以用个string类型的list来存储路径:
/// <summary>
/// 获取文件夹下的所有table路径
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static List<string> GetFilePathList(string path)
{
List<string> list = new List<string>();
string[] arr = Directory.GetFileSystemEntries(path);
for (int i = 0; i < arr.Length; i++)
{
if (File.GetAttributes(arr[i]).CompareTo(FileAttributes.Directory) > 0)
{
list.Add(arr[i]);
Debug.Log(arr[i]);
}
}
return list;
}
然后根据路径读取表格内容:
/// <summary>
/// 读取excel文件内容
/// </summary>
/// <param name="filePath">文件路径</param>
/// <param name="columnNum">列数</param>
/// <param name="rowNum">行数</param>
/// <returns></returns>
public static DataRowCollection ReadExcel(string filePath, ref int columnNum, ref int rowNum)
{
FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
DataSet result = excelReader.AsDataSet();
//Tables[0] 下标0表示excel文件中第一张表的数据
columnNum = result.Tables[0].Columns.Count;
rowNum = result.Tables[0].Rows.Count;
return result.Tables[0].Rows;
}
根据表格的设定,第一行为变量名,第二行为类型,然后就可以开始生成类了,关于生成cs文件,我tm直接拼的:
/// <summary>
/// 生成“Tab_XXX”的类,每个表对应一个cs文件
/// </summary>
/// <param name="fileName">表格名称</param>
/// <param name="TableData">表格数据</param>
/// <param name="columnNum">表格列数</param>
public static void CreatNewClass(string fileName, DataRowCollection TableData, int columnNum)
{
string FileName = "Tab_" + fileName;
string FilePath = ExcelConfig.TableClassPath + FileName + ".cs";
StringBuilder sbCode = new StringBuilder();
sbCode.AppendLine("using System.Collections;");
sbCode.AppendLine("using System.Collections.Generic;");
sbCode.AppendLine("using UnityEngine;");
sbCode.AppendLine(" ");
sbCode.AppendLine("public class Tab_"+fileName);
sbCode.AppendLine("{");
for (int i = 0; i < columnNum; i++)
{
string VariableName = TableData[0][i].ToString();
string VariableType = TableData[1][i].ToString();
switch (VariableType)
{
case "INT":
sbCode.AppendLine(" public int " + VariableName + ";");
break;
case "STRING":
sbCode.AppendLine(" public string " + VariableName + ";");
break;
}
}
sbCode.AppendLine("}");
File.WriteAllText(FilePath, sbCode.ToString());
Debug.Log(FileName + ".cs文件生成完毕。");
}
/// <summary>
/// 开始生成表格的类
/// </summary>
public static void BeginCreatTableClass()
{
List<string> filePathList = GetFilePathList(ExcelConfig.excelsFolderPath);//拿到所有文件路径,里面包括".xlsx"和".xlsx.meta"结尾的路径
for (int i = 0; i < filePathList.Count; i++)
{
string selectionExt = System.IO.Path.GetExtension(filePathList[i]);//拿到文件后缀".xlsx"和".xlsx.meta"
if (selectionExt != ".xlsx")//因为文件导入unity后会有meta文件,这个就不能走逻辑
{
continue;
}
else
{
//获得表数据
int columnNum = 0, rowNum = 0;
DataRowCollection collect = ReadExcel(filePathList[i], ref columnNum, ref rowNum);
string FileName = filePathList[i].Remove(filePathList[i].Length - selectionExt.Length);
FileName = FileName.Substring(ExcelConfig.excelsFolderPath.Length);
//开始生成类
CreatNewClass(FileName, collect, columnNum);
}
}
}
到这步会在我们指定的文件目录下生成相应的类文件:
然后我们就可以开始生成TableManager了,里面的方法包括拿到整个Ecxel数据的,也包括拿到单行数据的,生成代码是这样的:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Data;
public class TableManager
{
static Dictionary<int, Tab_Tasks> TasksDic = null;
//回整个数据
public static Dictionary<int, Tab_Tasks> CreatTasksArrayWithExcel()
{
if (TasksDic != null) return TasksDic;//如果之前内存中有了,直接返回,提高读取速度
TasksDic = new Dictionary<int, Tab_Tasks>();
string filePath = ExcelConfig.excelsFolderPath + "Tasks.xlsx";
int columnNum = 0, rowNum = 0;
DataRowCollection collect = CreatTableClass.ReadExcel(filePath, ref columnNum, ref rowNum);
Tab_Tasks[] array = new Tab_Tasks[rowNum - 4];
for (int i = 4; i < rowNum; i++)
{
Tab_Tasks Tasks = new Tab_Tasks();
Tasks.Id = int.Parse(collect[i][0].ToString());
Tasks.Name = collect[i][1].ToString();
Tasks.Act = int.Parse(collect[i][2].ToString());
Tasks.Scene = int.Parse(collect[i][3].ToString());
Tasks.Text = collect[i][4].ToString();
Tasks.Passed = collect[i][5].ToString();
TasksDic.Add(Tasks.Id, Tasks);
}
return TasksDic;
}
//根据id拿对象
public static Tab_Tasks GetTasksById(int id)
{
Tab_Tasks ret = null;
var TasksDic = CreatTasksArrayWithExcel();
TasksDic.TryGetValue(id, out ret);
return ret;
}
}
生成这个方式也跟上面一样,别写错就行了。
整个代码:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Text;
using System.Data;
using Excel;
//using Microsoft.CSharp;
public class CreatTableClass
{
/// <summary>
/// 生成“Tab_XXX”的类,每个表对应一个cs文件
/// </summary>
/// <param name="fileName">表格名称</param>
/// <param name="TableData">表格数据</param>
/// <param name="columnNum">表格列数</param>
public static void CreatNewClass(string fileName, DataRowCollection TableData, int columnNum)
{
string FileName = "Tab_" + fileName;
string FilePath = ExcelConfig.TableClassPath + FileName + ".cs";
StringBuilder sbCode = new StringBuilder();
sbCode.AppendLine("using System.Collections;");
sbCode.AppendLine("using System.Collections.Generic;");
sbCode.AppendLine("using UnityEngine;");
sbCode.AppendLine(" ");
sbCode.AppendLine("public class Tab_"+fileName);
sbCode.AppendLine("{");
for (int i = 0; i < columnNum; i++)
{
string VariableName = TableData[0][i].ToString();
string VariableType = TableData[1][i].ToString();
switch (VariableType)
{
case "INT":
sbCode.AppendLine(" public int " + VariableName + ";");
break;
case "STRING":
sbCode.AppendLine(" public string " + VariableName + ";");
break;
}
}
sbCode.AppendLine("}");
File.WriteAllText(FilePath, sbCode.ToString());
Debug.Log(FileName + ".cs文件生成完毕。");
}
/// <summary>
/// 开始生成表格的类
/// </summary>
public static void BeginCreatTableClass()
{
List<string> filePathList = GetFilePathList(ExcelConfig.excelsFolderPath);//拿到所有文件路径,里面包括".xlsx"和".xlsx.meta"结尾的路径
for (int i = 0; i < filePathList.Count; i++)
{
string selectionExt = System.IO.Path.GetExtension(filePathList[i]);//拿到文件后缀".xlsx"和".xlsx.meta"
if (selectionExt != ".xlsx")
{
continue;
}
else
{
//获得表数据
int columnNum = 0, rowNum = 0;
DataRowCollection collect = ReadExcel(filePathList[i], ref columnNum, ref rowNum);
string FileName = filePathList[i].Remove(filePathList[i].Length - selectionExt.Length);
FileName = FileName.Substring(ExcelConfig.excelsFolderPath.Length);
//开始生成类
CreatNewClass(FileName, collect, columnNum);
}
}
}
/// <summary>
/// 生成TableManager.cs
/// </summary>
/// <param name="sbCode">单列</param>
/// <param name="fileName"></param>
/// <param name="TableData"></param>
/// <param name="columnNum"></param>
public static void CreatTableManager(StringBuilder sbCode, string fileName, DataRowCollection TableData, int columnNum)
{
string FileName = "Tab_" + fileName;
sbCode.AppendLine(" static Dictionary<int, "+FileName+"> "+fileName+"Dic = null;");
sbCode.AppendLine(" public static Dictionary<int, "+ FileName + "> Creat"+ fileName + "ArrayWithExcel()");
sbCode.AppendLine(" {");
sbCode.AppendLine(" if ("+ fileName + "Dic != null) return "+ fileName + "Dic;");
sbCode.AppendLine(" "+ fileName + "Dic = new Dictionary<int, "+ FileName + ">();");
sbCode.AppendLine(" string filePath = ExcelConfig.excelsFolderPath + "+"\"" + fileName + ".xlsx"+"\";");
sbCode.AppendLine(" int columnNum = 0, rowNum = 0;");
sbCode.AppendLine(" DataRowCollection collect = CreatTableClass.ReadExcel(filePath, ref columnNum, ref rowNum);");
sbCode.AppendLine(" " + FileName + "[] array = new " + FileName + "[rowNum - 4];");
sbCode.AppendLine(" for (int i = 4; i < rowNum; i++)");
sbCode.AppendLine(" {");
sbCode.AppendLine(" " + FileName + " " + fileName + " = new " + FileName + "();");
for (int j = 0; j < columnNum; j++)
{
string VariableName = TableData[0][j].ToString();
string VariableType = TableData[1][j].ToString();
if (VariableType == "INT")
{
sbCode.AppendLine(" " + fileName + "." + VariableName + " = int.Parse(collect[i][" + j + "].ToString());");
}
else
{
sbCode.AppendLine(" " + fileName + "." + VariableName + " = collect[i][" + j + "].ToString();");
}
}
sbCode.AppendLine(" "+ fileName + "Dic.Add("+ fileName + ".Id, "+ fileName + ");");
sbCode.AppendLine(" }");
sbCode.AppendLine(" return "+ fileName + "Dic;");
sbCode.AppendLine(" }");
//生成拿到表格单列方法
sbCode.AppendLine(" ");
sbCode.AppendLine(" public static " + FileName + " Get" + fileName + "ById(int id)");
sbCode.AppendLine(" {");
sbCode.AppendLine(" " + FileName + " ret = null;");
sbCode.AppendLine(" var " + fileName + "Dic = Creat"+ fileName + "ArrayWithExcel();");
sbCode.AppendLine(" " + fileName + "Dic.TryGetValue(id, out ret);");
sbCode.AppendLine(" return ret;");
sbCode.AppendLine(" }");
sbCode.AppendLine(" ");
}
/// <summary>
/// 开始生成TableManager.cs
/// </summary>
public static void BeginCreatTableManager()
{
List<string> filePathList = GetFilePathList(ExcelConfig.excelsFolderPath);//拿到所有文件路径,里面包括".xlsx"和".xlsx.meta"结尾的路径
StringBuilder sbCode = new StringBuilder();
sbCode.AppendLine("using System.Collections;");
sbCode.AppendLine("using System.Collections.Generic;");
sbCode.AppendLine("using UnityEngine;");
sbCode.AppendLine("using System.Data;");
sbCode.AppendLine(" ");
sbCode.AppendLine("public class TableManager");
sbCode.AppendLine("{");
for (int i = 0; i < filePathList.Count; i++)
{
string selectionExt = System.IO.Path.GetExtension(filePathList[i]);//拿到文件后缀".xlsx"和".xlsx.meta"
if (selectionExt != ".xlsx")
{
continue;
}
else
{
//获得表数据
int columnNum = 0, rowNum = 0;
DataRowCollection collect = ReadExcel(filePathList[i], ref columnNum, ref rowNum);
string FileName = filePathList[i].Remove(filePathList[i].Length - selectionExt.Length);
FileName = FileName.Substring(ExcelConfig.excelsFolderPath.Length);
//开始生成TableManager
CreatTableManager(sbCode, FileName, collect, columnNum);
}
}
sbCode.AppendLine("}");
File.WriteAllText(ExcelConfig.TableManagerPath+"TableManager.cs", sbCode.ToString());
Debug.Log("TableManager.cs文件生成完毕。");
}
/// <summary>
/// 读取excel文件内容
/// </summary>
/// <param name="filePath">文件路径</param>
/// <param name="columnNum">列数</param>
/// <param name="rowNum">行数</param>
/// <returns></returns>
public static DataRowCollection ReadExcel(string filePath, ref int columnNum, ref int rowNum)
{
FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
DataSet result = excelReader.AsDataSet();
//Tables[0] 下标0表示excel文件中第一张表的数据
columnNum = result.Tables[0].Columns.Count;
rowNum = result.Tables[0].Rows.Count;
return result.Tables[0].Rows;
}
/// <summary>
/// 获取文件夹下的所有table路径
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static List<string> GetFilePathList(string path)
{
List<string> list = new List<string>();
string[] arr = Directory.GetFileSystemEntries(path);
for (int i = 0; i < arr.Length; i++)
{
if (File.GetAttributes(arr[i]).CompareTo(FileAttributes.Directory) > 0)
{
list.Add(arr[i]);
Debug.Log(arr[i]);
}
}
return list;
}
}