【Unity】Unity开发进阶(八)Windows解析Excel报错问题、跨平台解析Excel文件


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学习笔记目录整理

猜你喜欢

转载自blog.csdn.net/xiaoyaoACi/article/details/127415254