Windows解析Excel
在前面的文章 【Unity】U3D TD游戏制作实例(二)配置关卡、加载Excel配置文件 中,我们使用Unity读取了Excel文件。但在打包exe后会报错(NullReferenceException: Object reference not set to an instance of an object,Excel.ExcelOpenXmlReader.IsDBNull ),这是因为Unity打包时没有带上I18N文件,下面说一下解决方案。
解决方案
首先需要找到以下文件:
- I18N.CJK.dll
- I18N.dll
- I18N.MidEast.dll
- I18N.Other.dll
- I18N.Rare.dll
- I18N.West.dll
在网上查到的资料都说这些文件是存在 C:\Program Files\Unity\Editor\Data\Mono\lib\mono\unity 路径下的,可能资料比较旧,现在的文件结构已经不是这样的了。
后续我找到了 E:\Program Files\Unity Hub\Editor\2021.3.8f1c1\Editor\Data\MonoBleedingEdge\lib\mono 文件夹,发现里面有很多个版本的API中都带有这些 I18N 文件,我自己试了几个版本,发现 unityjit-win32 文件夹下的版本是可用的。
需要拷贝的文件如下:
如果还是找不到也没有关系,可以选择从这个链接下载:https://download.csdn.net/download/xiaoyaoACi/86783861 Unity读取Excel需要的工具DLL。
或者直接私信我,我发给你也行。
跨平台解析Excel文件
在不同平台运行时,获取配置文件的方式也是不同的。针对这种情况,我们可以做一个配置文件管理器,先上代码:
using UnityEngine;
using System.IO;
using Excel;
/// <summary>
/// 配置管理器
/// 用于在不同的运行环境下加载配置
/// </summary>
public class ConfigManager
{
/// <summary>
/// 文件路径前缀
/// </summary>
private static readonly string _prifix =
#if UNITY_EDITOR || UNITY_STANDALONE_WIN
Application.streamingAssetsPath;
#elif UNITY_IOS
=Application.dataPath;
#elif UNITY_ANDROID
="jar:file:/" + "/" + Application.dataPath + "!/assets";
#else
=string.Empty;
#endif
/// <summary>
/// 实际文件路径
/// </summary>
public string path;
/// <summary>
/// 根据运行环境生成文件路径
/// </summary>
/// <param name="fragments">路径片段。例:new string[] { "Configs", "LevelConfig", "Level_1001.xlsx" } </param>
public void InitPath(params string[] fragments)
{
path = _prifix;
string separator = "/";
#if UNITY_EDITOR || UNITY_IOS || UNITY_STANDALONE_WIN
#elif UNITY_ANDROID
separator = "//";
#endif
foreach (var frag in fragments)
{
path += separator + frag;
}
}
/// <summary>
/// 加载Excel文件
/// </summary>
/// <param name="fragments">路径片段。例:new string[] { "Configs", "LevelConfig", "Level_1001.xlsx" } </param>
/// <returns></returns>
public IExcelDataReader LoadExcel(params string[] fragments)
{
InitPath(fragments);
#if UNITY_EDITOR || UNITY_IOS || UNITY_STANDALONE_WIN
if (File.Exists(path))
{
// 解析Excel
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
// 创建Excel读取类
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(fs);
return excelReader;
}
else
{
Debug.Log("[File not found] - " + path);
}
#elif UNITY_ANDROID
WWW www = new WWW(path);
while(!www.isDone)
{
yield return www;
all = www.text;
//ParseXml(www);
}
#endif
return null;
//return throw FileNotFoundException("File not found !");
}
public void CloseExcel()
{
}
}
目前版本是将 IExcelDataReader excelReader 对象返回给调用者,后续可以对 ExcelDataReader 做二次封装,根据不同情况提供不同的调用代码,比如提供常用的 Read 、GetString 、 GetInt32 等方法。
下面上一段使用 ConfigManager 的代码:
ConfigManager configManager = new ConfigManager();
// 创建关卡配置对象
_levelConfig = new LevelConfig();
IExcelDataReader excelReader = configManager.LoadExcel(new string[] {
"Configs", "LevelConfig", "Level_1001.xlsx" });
// 读取
int index = 0;
// 移动到第四行
for (; index < 4; index++)
{
excelReader.Read();
}
_levelConfig.LevelCode = excelReader.GetString(1);
_levelConfig.RoundCount = excelReader.GetInt32(2);
// 跳过空白行和标题行
excelReader.Read();
excelReader.Read();
_levelConfig.EnemyConfigs = new List<EnemyConfig>();
for (; index <= 4 + _levelConfig.RoundCount; index++)
{
excelReader.Read();
EnemyConfig emConfig = new EnemyConfig();
emConfig.RoundCount = excelReader.GetInt32(1);
emConfig.PrefabPath = excelReader.GetString(2);
emConfig.EnemyCount = excelReader.GetInt32(3);
emConfig.GenInterval = excelReader.GetFloat(4);
emConfig.EnemyHP = excelReader.GetFloat(5);
emConfig.EnemyAttack = excelReader.GetFloat(6);
emConfig.EnemySpeed = excelReader.GetFloat(7);
_levelConfig.EnemyConfigs.Add(emConfig);
}
更多内容请查看总目录【Unity】Unity学习笔记目录整理