Unity读取和写入本地Excel表格数据完整指南
1. 前言
在Unity游戏开发中,经常需要处理配置数据,如角色属性、关卡信息、道具列表等。Excel表格因其直观的表格形式和强大的数据处理能力,常被用作数据源。本文将详细介绍在Unity中读取和写入本地Excel表格数据的几种主流方案,并提供完整的代码示例。
2. 方案选择与准备
Unity本身不提供直接操作Excel文件的功能,需要借助第三方库。以下是几种常用方案:
- EPPlus(推荐):一个开源的.NET库,无需安装Office,支持读写.xlsx格式。
- NPOI:另一个流行的.NET开源库,支持.xls和.xlsx格式。
- ExcelDataReader:专注于读取Excel数据,轻量快速。
- Unity内置的TextAsset/CSV:将Excel另存为CSV,通过Unity的TextAsset读取。
本文将以EPPlus为例进行讲解,因为它功能全面、性能良好且无需依赖Office。
3. 环境配置
3.1 获取EPPlus库
访问 EPPlus GitHub仓库 下载最新Release的EPPlus.dll。或者通过NuGet包管理器安装。
3.2 导入Unity项目
- 在Unity项目Assets目录下创建
Plugins文件夹。 - 将下载的
EPPlus.dll放入Assets/Plugins中。 - 确保Unity编辑器设置中,该DLL的“平台兼容性”包含“Editor”和“Standalone”。
注意:EPPlus依赖.NET 4.x或更高版本。请在Unity的Player Settings->Other Settings->Configuration中将Scripting Backend设置为IL2CPP或Mono,并将Api Compatibility Level设置为.NET Framework或.NET Standard 2.0。
4. 读取Excel数据
以下示例演示如何读取一个名为GameConfig.xlsx的Excel文件,其第一张工作表结构如下:
| ID | Name | HP | Attack |
|---|---|---|---|
| 1001 | 英雄 | 100 | 20 |
| 1002 | 怪物 | 50 | 10 |
using System; using System.Collections.Generic; using System.IO; using OfficeOpenXml; using UnityEngine; public class ExcelReader : MonoBehaviour { // 定义数据结构类 [System.Serializable] public class CharacterData { public int ID; public string Name; public int HP; public int Attack; } void Start() { // Excel文件路径(放在Assets同级目录的Data文件夹下) string filePath = Path.Combine(Application.dataPath, "../Data/GameConfig.xlsx"); if (!File.Exists(filePath)) { Debug.LogError("Excel文件不存在: " + filePath); return; } // 使用EPPlus读取 FileInfo fileInfo = new FileInfo(filePath); using (ExcelPackage package = new ExcelPackage(fileInfo)) { // 获取第一个工作表 ExcelWorksheet worksheet = package.Workbook.Worksheets[0]; // 确定数据范围(假设第一行是标题) int rowCount = worksheet.Dimension.Rows; int colCount = worksheet.Dimension.Columns; List<CharacterData> dataList = new List<CharacterData>(); // 从第二行开始读取数据(跳过标题行) for (int row = 2; row <= rowCount; row++) { CharacterData data = new CharacterData(); data.ID = Convert.ToInt32(worksheet.Cells[row, 1].Value); data.Name = worksheet.Cells[row, 2].Value?.ToString(); data.HP = Convert.ToInt32(worksheet.Cells[row, 3].Value); data.Attack = Convert.ToInt32(worksheet.Cells[row, 4].Value); dataList.Add(data); Debug.Log($"读取: ID={data.ID}, Name={data.Name}, HP={data.HP}, Attack={data.Attack}"); } Debug.Log($"共读取 {dataList.Count} 条角色数据。"); } } }5. 写入Excel数据
以下示例演示如何创建一个新的Excel文件并写入数据。
using System.IO; using OfficeOpenXml; using UnityEngine; public class ExcelWriter : MonoBehaviour { void Start() { // 设置LicenseContext(EPPlus 5.0+ 需要) ExcelPackage.LicenseContext = LicenseContext.NonCommercial; // 定义要写入的数据 var dataList = new[] { new { ID = 2001, Name = "武器A", Price = 150, Type = "Sword" }, new { ID = 2002, Name = "武器B", Price = 300, Type = "Bow" }, new { ID = 2003, Name = "武器C", Price = 500, Type = "Staff" } }; // 文件保存路径 string savePath = Path.Combine(Application.dataPath, "../Data/WeaponData.xlsx"); // 创建Excel包和工作表 using (ExcelPackage package = new ExcelPackage()) { ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Weapons"); // 写入标题行 worksheet.Cells[1, 1].Value = "ID"; worksheet.Cells[1, 2].Value = "Name"; worksheet.Cells[1, 3].Value = "Price"; worksheet.Cells[1, 4].Value = "Type"; // 设置标题行样式 using (var range = worksheet.Cells[1, 1, 1, 4]) { range.Style.Font.Bold = true; range.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid; range.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightGray); } // 写入数据行 for (int i = 0; i < dataList.Length; i++) { int row = i + 2; // 从第二行开始 worksheet.Cells[row, 1].Value = dataList[i].ID; worksheet.Cells[row, 2].Value = dataList[i].Name; worksheet.Cells[row, 3].Value = dataList[i].Price; worksheet.Cells[row, 4].Value = dataList[i].Type; } // 自动调整列宽 worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns(); // 保存文件 FileInfo fileInfo = new FileInfo(savePath); package.SaveAs(fileInfo); Debug.Log("Excel文件已保存至: " + savePath); } } }6. 进阶技巧与注意事项
6.1 处理多种数据类型
Excel单元格可能包含字符串、数字、日期、布尔值等。读取时应进行类型判断和转换:
object cellValue = worksheet.Cells[row, col].Value; if (cellValue != null) { if (cellValue is double) intValue = Convert.ToInt32((double)cellValue); else if (cellValue is int) intValue = (int)cellValue; else if (cellValue is string) stringValue = cellValue.ToString(); // ... 其他类型处理 }6.2 跨平台路径处理
在Unity中,不同平台的持久化数据路径不同,应使用Application.persistentDataPath:
// 推荐:将Excel文件放在可读写目录 string excelPath = Path.Combine(Application.persistentDataPath, "Config/GameData.xlsx");6.3 性能优化
- 批量读取:使用
worksheet.Cells.Value获取整个区域的对象数组进行批量处理。 - 避免频繁创建/销毁:对于需要频繁读写的配置,可考虑在启动时加载到内存中的数据结构(如Dictionary、List)。
- 异步操作:读写大文件时使用
async/await或协程,避免阻塞主线程。
6.4 常见错误处理
- 文件被占用:确保在
using语句中操作ExcelPackage,以正确释放资源。 - 格式不匹配:EPPlus主要支持.xlsx格式,对于.xls文件建议使用NPOI。
- 权限问题:检查目标目录的读写权限。
7. 替代方案:CSV格式
如果数据量不大且结构简单,可将Excel另存为CSV,利用Unity内置的TextAsset读取:
// 将CSV文件放在Resources文件夹下 TextAsset csvFile = Resources.Load<TextAsset>("GameConfig"); string[] lines = csvFile.text.Split('\n'); foreach (string line in lines) { string[] fields = line.Split(','); // 解析每一行数据 }优点:无需第三方DLL,跨平台兼容性好。
缺点:不支持多工作表、单元格格式和公式。
8. 总结
在Unity中操作Excel数据,EPPlus是一个功能强大且易于集成的选择。本文提供了从环境配置、读取、写入到进阶优化的完整流程。关键步骤总结如下:
- 根据需求选择合适的库(EPPlus、NPOI等)。
- 正确配置Unity的.NET版本并导入DLL。
- 使用
ExcelPackage和ExcelWorksheet进行读写操作。 - 注意类型转换、路径处理和异常捕获。
- 对于简单需求,可考虑使用CSV格式作为轻量级替代方案。
掌握这些技能后,你可以轻松地将Excel表格作为强大的数据配置工具集成到Unity项目中。
