【Unity】Excel配置工具
1、功能介绍
通过Excel表配置表数据,一键生成对应Excel配置表的数据结构类、数据容器类、已经二进制数据文件,加载二进制数据文件获取所有表数据
需要使用Excel读取的dll包
2、关键代码
2.1 ExcelTool类
实现一键生成Excel配置表的数据结构类、数据容器类、已经二进制数据文件
using Excel;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;public class ExcelTool
{/// <summary>/// excel文件存放路径/// </summary>public static string EXCEL_PATH = Application.dataPath + "/ArtRes/Excel/";/// <summary>/// 数据结构类脚本存储路径/// </summary>public static string DATA_CLASS_PATH = Application.dataPath + "/Scripts/ExcelData/DataClass/";/// <summary>/// 容器类脚本存储路径/// </summary>public static string DATA_CONTAINER_PATH = Application.dataPath + "/Scripts/ExcelData/Container/";/// <summary>/// 二进制数据存储路径/// </summary>//public static string DATA_BINARY_PATH = Application.streamingAssetsPath + "/Bianry/";/// <summary>/// 真正内容开始行号/// </summary>public static int BEGIN_INDEX = 4;[MenuItem("GameTool/GenerateExcelInfo")]private static void GenerateExcelInfo(){//加载指定路径中的所有Excel文件 用于生成对应的3个文件DirectoryInfo dInfo = Directory.CreateDirectory(EXCEL_PATH);//得到指定路径中的所有文件信息 相当于就是得到所有的Exce1表FileInfo[] files = dInfo.GetFiles();//数据容器DataTableCollection tableCollection;for (int i = 0; i < files.Length; i++){//如果不是Excel文件就不要处理if (files[i].Extension != ".xlsx" && files[i].Extension != ".xls")continue;//打开一个excel文件得到其中所有表的数据using(FileStream fs = files[i].Open(FileMode.Open, FileAccess.Read)){IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(fs);tableCollection = excelReader.AsDataSet().Tables;fs.Close();}//遍历文件中的所有表的信息foreach (DataTable table in tableCollection){Debug.Log(table.TableName);//生成数据结构类GenerateExcelDataClass(table);//生成容器类GenerateExcelContainer(table);//生成2进制数据GenerateExcelBinary(table);}}}/// <summary>/// 生成Excel表对应的数据结构类/// </summary>/// <param name="table"></param>private static void GenerateExcelDataClass(DataTable table){//字段名行DataRow rowName = GetVariableNameRow(table);//字段类型行DataRow rowType = GetVariableTypeRow(table);//判断路径是否存在 没有的话 就创建文件夹if (!Directory.Exists(DATA_CLASS_PATH))Directory.CreateDirectory(DATA_CLASS_PATH);//如果我们要生成对应的数据结构类脚本 其实就是通过代码进行字符串拼接 然后存进文件就行了string str = "public class " + table.TableName + "\n{\n";//变量进行字符串拼接for (int i = 0; i < table.Columns.Count; i++){str += "\tpublic " + rowType[i].ToString() + " " + rowName[i].ToString() + ";\n";}str += "}\n";//把拼接好的字符串存进占地文件中File.WriteAllText(DATA_CLASS_PATH + table.TableName + ".cs", str);//刷新Project窗口AssetDatabase.Refresh();}/// <summary>/// 生成Excel表对应的数据容器类/// </summary>/// <param name="table"></param>private static void GenerateExcelContainer(DataTable table){//得到主键索引int keyIndex = GetKeyIndex(table);//得到字段类型行DataRow rowType = GetVariableTypeRow(table);//没有路径就创建路径if (!Directory.Exists(DATA_CONTAINER_PATH)) Directory.CreateDirectory (DATA_CONTAINER_PATH);string str = "using System.Collections.Generic;\n\n";str += "public class " + table.TableName + "Container" + "\n{\n";str += "\tpublic Dictionary<" + rowType[keyIndex].ToString() + ", " + table.TableName + ">";str += "dataDic = new Dictionary<" + rowType[keyIndex].ToString() + ", " + table.TableName + ">();\n";str += "}";File.WriteAllText(DATA_CONTAINER_PATH + table.TableName + "Container.cs", str);//刷新Project窗口AssetDatabase.Refresh();}/// <summary>/// 生成Excel 2进制数据/// </summary>/// <param name="table"></param>private static void GenerateExcelBinary(DataTable table){//没有路径创建路径if(!Directory.Exists(BinaryDataMgr.DATA_BINARY_PATH)) Directory.CreateDirectory(BinaryDataMgr.DATA_BINARY_PATH);//创建一个2进制文件进行写入using(FileStream fs = new FileStream(BinaryDataMgr.DATA_BINARY_PATH + table.TableName + ".zhou", FileMode.OpenOrCreate, FileAccess.Write)){//存储具体的Excel对应的2进制信息//1.先要存储需要写的行数//-4 因为前面4行是配置规则 不是需要记录的数据内容fs.Write(BitConverter.GetBytes(table.Rows.Count - 4), 0, 4);//2.存储主键的变量名string keyName = GetVariableNameRow(table)[GetKeyIndex(table)].ToString();byte[] bytes = Encoding.UTF8.GetBytes(keyName);//存储字符串字节数据的长度fs.Write(BitConverter.GetBytes(keyName.Length), 0, 4);//存储字符串字节数组fs.Write(bytes, 0, bytes.Length);//遍历所有内容的行 进行2进制的写入DataRow row;//得到类型行 根据类型来决定应该如何写入DataRow rowType = GetVariableTypeRow(table);for (int i = BEGIN_INDEX; i < table.Rows.Count; i++){//得到一行的数据row = table.Rows[i];for (int j = 0; j < table.Columns.Count; j++){switch(rowType[j].ToString()){case "int":fs.Write(BitConverter.GetBytes(int.Parse(row[j].ToString())), 0, 4);break;case "float":fs.Write(BitConverter.GetBytes(float.Parse(row[j].ToString())), 0, 4);break;case "bool":fs.Write(BitConverter.GetBytes(bool.Parse(row[j].ToString())), 0, 1);break;case "string":bytes = Encoding.UTF8.GetBytes(row[j].ToString());//写入字节数据的长度fs.Write(BitConverter.GetBytes(bytes.Length), 0, 4);//写入字符串字节数组fs.Write(bytes, 0, bytes.Length);break;}}}fs.Close();}AssetDatabase.Refresh();}/// <summary>/// 获取变量名所在行/// </summary>/// <param name="table"></param>/// <returns></returns>private static DataRow GetVariableNameRow(DataTable table){return table.Rows[0];}/// <summary>/// 获取变量类型所在行/// </summary>/// <param name="table"></param>/// <returns></returns>private static DataRow GetVariableTypeRow(DataTable table){return table.Rows[1];}/// <summary>/// 获取主键索引/// </summary>/// <param name="table"></param>/// <returns></returns>private static int GetKeyIndex(DataTable table){DataRow row = table.Rows[2];for (int i = 0;i < table.Columns.Count; i++){if (row[i].ToString() == "key")return i;}return 0;}}
2.2 BinaryDataMgr
保存数据,读取数据
读取Excel表生成的二进制文件,加载到内容中以供使用
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using UnityEngine;/// <summary>
/// 2进制数据管理器
/// </summary>
public class BinaryDataMgr
{private static BinaryDataMgr instance = new BinaryDataMgr();public static BinaryDataMgr Instance => instance;private BinaryDataMgr() { }/// <summary>/// 用于存储所有Excel表数据的容器/// </summary>private Dictionary<string, object> tableDic = new Dictionary<string, object>();/// <summary>/// 数据存储路径/// </summary>private static string SAVE_PATH = Application.persistentDataPath + "/Data/";/// <summary>/// 二进制数据存储路径/// </summary>public static string DATA_BINARY_PATH = Application.streamingAssetsPath + "/Bianry/";public void InitData(){//加载自己的表到内存//LoadTable<TowerInfoContainer, TowerInfo>();//LoadTable<PlayerInfo1Container, PlayerInfo1>();//LoadTable<TestInfoContainer, TestInfo>();}/// <summary>/// 加载Excel表的2进制数据到内存中/// </summary>/// <typeparam name="T">容器类名</typeparam>/// <typeparam name="K">数据结构体类名</typeparam>public void LoadTable<T, K>(){//读取Excel表对应的2进制文件 来进行解析using (FileStream fs = File.Open(DATA_BINARY_PATH + typeof(K).Name + ".zhou", FileMode.Open, FileAccess.Read)){byte[] bytes = new byte[fs.Length];fs.Read(bytes, 0, bytes.Length);fs.Close();//用于记录当前读取了多少字节int index = 0;//读取多少行数据int count = BitConverter.ToInt32 (bytes, index);index += 4;//读取主键的名字int keyNameLength = BitConverter.ToInt32 (bytes, index);index += 4;string keyName = Encoding.UTF8.GetString(bytes, index, keyNameLength);index += keyNameLength;//创建容器类对象Type contaninerType = typeof (T);object contaninerObj = Activator.CreateInstance(contaninerType);//得到数据结构类TypeType classType = typeof(K);//通过反射得到数据结构类 所有字段的信息FieldInfo[] infos = classType.GetFields();//读取每一行的信息for (int i = 0; i < count; i++){//实例化一个结构对象类 对象object dataObj = Activator.CreateInstance(classType);foreach (FieldInfo info in infos){if(info.FieldType == typeof(int)){//相当于将2进制数据转为int 然后赋值给对应字段info.SetValue(dataObj, BitConverter.ToInt32(bytes, index));index += 4;}else if (info.FieldType == typeof(float)){info.SetValue(dataObj, BitConverter.ToSingle(bytes, index));index += 4;}else if (info.FieldType == typeof(bool)){info.SetValue(dataObj, BitConverter.ToBoolean(bytes, index));index += 1;}else if (info.FieldType == typeof(string)){//读取字符串字节数组长度int length = BitConverter.ToInt32(bytes, index);index += 4;info.SetValue(dataObj, Encoding.UTF8.GetString(bytes, index, length));index += length;}}//读取完一行的数据后 将这个数据存到容器对象中object dicObj = contaninerType.GetField("dataDic").GetValue(contaninerObj);//得到容器字段对象MethodInfo mInfo = dicObj.GetType().GetMethod("Add");//得到数据结构类对象中 指定主键字段的值object keyValue = classType.GetField(keyName).GetValue(dataObj);mInfo.Invoke(dicObj, new object[] { keyValue, dataObj });}//把读取完的表记录下来tableDic.Add(typeof(T).Name, contaninerObj);fs.Close();}}/// <summary>/// 得到一张表的信息/// </summary>/// <typeparam name="T">容器类名</typeparam>/// <returns></returns>public T GetTable<T>() where T : class{string tableName = typeof(T).Name;if(tableDic.ContainsKey(tableName)){return tableDic[tableName] as T;}return null;}/// <summary>/// 存储类对象数据/// </summary>/// <param name="data"></param>/// <param name="fileName"></param>public void Save(object data, string fileName){if(!Directory.Exists(SAVE_PATH)){Directory.CreateDirectory(SAVE_PATH);}using(FileStream fs = new FileStream(SAVE_PATH + fileName + ".zhou", FileMode.OpenOrCreate, FileAccess.Write)){BinaryFormatter bf = new BinaryFormatter();bf.Serialize(fs, data);fs.Flush();fs.Close();}}/// <summary>/// 读取2进制数据转换成对象/// </summary>/// <typeparam name="T"></typeparam>/// <param name="fileName"></param>/// <returns></returns>public T Load<T>(string fileName) where T : class{if(!File.Exists(SAVE_PATH + fileName + ".zhou")){return default(T);}T data;using(FileStream fs = new FileStream(SAVE_PATH + fileName + ".zhou", FileMode.Open, FileAccess.Read)){BinaryFormatter bf = new BinaryFormatter();data = bf.Deserialize(fs) as T;fs.Close();}return data;}}
3、使用步骤
3.1 根据规则创建Excel配置表
创建的Excel表需要放置到ArtRes/Excel路径下
Excel配置规则
- 第一行:字段名
- 第二行:字段类型(字段类型一定不要配置错误,字段类型目前只支持int float bool string)如果想要在添加类型,需要ExcelTool的GenerateExcelBianary和BianryDataMgr的LoadTable方法当中对应添加读写的逻辑
- 第三行:主键是哪一个字段 需要通过key来标识主键
- 第四行:描述信息(只是给别人看,不会有别的作用)
- 第五行~第n行:就是具体数据信息
- 下方的表名决定类数据结构类,容器类,2进制文件的文件名
3.2 点击按钮GenerateExcelInfo
生成所有Excel表的数据结构类、数据结构容器类和二进制数据文件
3.3 完善BinaryDataMgr的InitData()方法,将自己创建的表进行加载
public void InitData(){//加载自己的表到内存//LoadTable<TowerInfoContainer, TowerInfo>();//LoadTable<PlayerInfo1Container, PlayerInfo1>();//LoadTable<TestInfoContainer, TestInfo>();LoadTable<WeaponItemContainer, WeaponItem>();}
3.4 初始化数据,加载数据到内存
BinaryDataMgr.Instance.InitData() 加载二进制数据到内存当中
BinaryDataMgr.Instance.GetTable<TowerInfoContainer>() 获取需要使用的表的数据
BinaryDataMgr.Instance.InitData();WeaponItemContainer data = BinaryDataMgr.Instance.GetTable<WeaponItemContainer>();foreach (var item in data.dataDic.Values){Debug.Log($"id:{item.id}-name:{item.name}-des:{item.des}-money:{item.money}-ATK:{item.atk}");}
相关文章:

【Unity】Excel配置工具
1、功能介绍 通过Excel表配置表数据,一键生成对应Excel配置表的数据结构类、数据容器类、已经二进制数据文件,加载二进制数据文件获取所有表数据 需要使用Excel读取的dll包 2、关键代码 2.1 ExcelTool类 实现一键生成Excel配置表的数据结构类、数据…...
001 线性查找(lua)
文章目录 迭代器主程序 迭代器 -- 定义一个名为 linearSearch 的函数,它接受两个参数:data(一个数组)和 target(一个目标值) function linearSearch(data, target) -- 使用 for 循环遍历数组 data&…...

数据结构之链表
储备知识: 线性表 :一对一的数据所组成的关系称为线性表。 线性表是一种数据内部的逻辑关系,与存储形式无关线性表既可以采用连续的顺序存储(数组),也可以采用离散的链式存储(链表)顺序表和链表都称为线性表 顺序存储就是将数据存…...
【小工具】 Unity相机宽度适配
相机默认是根据高度适配的,但是在部分游戏中需要根据宽度进行适配 实现步骤 定义标准屏幕宽、高判断标准屏幕宽高比与当前的是否相等通过**(标准宽度/当前宽度) (标准高度 / 当前高度)**计算缩放调整相机fieldOfView即…...
centos误删yum和python
在下载pkdg时,因为yum报错坏的解释器,然后误删了yum和python。 在下载各种版本,创建各种软连接,修改yum文件都不好使后,发现了这样一个方法:Centos: 完美解决python升级导致的yum报错问题(相信…...

WP黑格导航主题BlackCandy
BlackCandy-V2.0全新升级!首推专题区(推荐分类)更多自定义颜色!选择自己喜欢的色系,焕然一新的UI设计,更加扁平和现代化! WP黑格导航主题BlackCandy...
elasticsearch底层核心组件
Elasticsearch是一个高度可扩展的开源全文搜索和分析引擎,它基于Apache Lucene构建,并添加了分布式特性。以下是Elasticsearch的一些底层核心组件: 1. **Lucene**: - Elasticsearch基于Apache Lucene,一个高性能的…...

EasyExcel数据导入
前言: 我先讲一种网上信息的获取方式把,虽然我感觉和后面的EasyExcel没有什么关系,可能是因为这个项目这个操作很难实现,不过也可以在此记录一下,如果需要再拆出来也行。 看上了网页信息,怎么抓到&#x…...

20240630 每日AI必读资讯
📚全美TOP 5机器学习博士发帖吐槽:实验室H100数量为0! - 普林斯顿、哈佛「GPU豪门」,手上的H100至少三四百块,然而绝大多数ML博士一块H100都用不上 - 年轻的研究者们纷纷自曝自己所在学校或公司的GPU情况:…...

第十一章 Qt的模型视图
目录 一、模型/视图的原理 1、原理分析 2、模型(数据模型) 3、视图 4、代理 二、文件系统模型 1、项目练习 2、UI 设计 3、代码实现 三、字符串链表模型 QStringListModel 1、项目效果 2、项目实现 四、标准项模型(QStandardItemModel) 1、模型分析 2、项目效…...

力扣 单词规律
所用数据结构 哈希表 核心方法 判断字符串pattern 和字符串s 是否存在一对一的映射关系,按照题意,双向连接的对应规律。 思路以及实现步骤 1.字符串s带有空格,因此需要转换成字符数组进行更方便的操作,将字符串s拆分成单词列表…...

10款好用不火的PC软件,真的超好用!
AI视频生成:小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/市场上有很多软件,除了那些常见的大众化软件,还有很多不为人知的小众软件,它们的作用非常强大,简洁…...

Windows怎么实现虚拟IP
在做高可用架构时,往往需要用到虚拟IP,在linux上面有keepalived来实现虚拟ip的设置。在windows上面该怎么弄,keepalived好像也没有windows版本,我推荐一款浮动IP软件PanguVip,它可以实现windows上面虚拟ip的漂移。设置…...

【计算机网络】HTTP——基于HTTP的功能追加协议(个人笔记)
学习日期:2024.6.29 内容摘要:基于HTTP的功能追加协议和HTTP/2.0 HTTP的瓶颈与各功能追加协议 需求的产生 在Facebook、推特、微博等平台,每分每秒都会有人更新内容,我们作为用户当然希望时刻都能收到最新的消息,为…...

【多媒体】Java实现MP4视频播放器【JavaFX】【音视频播放】
在Java中播放视频可以使用多种方案,最常见的是通过Swing组件JFrame和JLabel来嵌入JMF(Java Media Framework)或Xuggler。不过,JMF已经不再被推荐使用,而Xuggler是基于DirectX的,不适用于跨平台。而且上述方案都需要使用第三方库。…...

2024 Parallels Desktop for Mac 功能介绍
Parallels Desktop的简介 Parallels Desktop是一款由Parallels公司开发的桌面虚拟化软件,它允许用户在Mac上运行Windows和其他操作系统。通过强大的技术支持,用户无需重新启动电脑即可在Mac上运行Windows应用程序,实现了真正的无缝切换。 二…...

颍川韩氏,来自战国七雄韩国的豪族
颍川是战国七雄韩国故土,韩国被秦国灭国后,王公贵族们除了坚决反秦的被杀了外,大部分都留存了下来。这些人在楚、汉反秦战争中,成为反秦统一战线的重要力量,其中两人先后被封为重新恢复的韩国的国王。 一个是横阳君韩…...
Spring boot中如何使用Thymeleaf模板
大家好,我是 网创有方。今天给大家分享下Spring boot中如何使用Thymeleaf模板。 在 IntelliJ IDEA 中使用 Thymeleaf 模板引擎来开发 Spring Boot 应用程序是相对简单的。以下是一些基本步骤,帮助你在 IDEA 中设置和使用 Thymeleaf: 创建一个…...

单片机学习(14)--DS18B20温度传感器
DS18B20温度传感器 13.1DS18B20温度传感器基础知识1.DS18B20介绍2.引脚及应用电路3.内部结构框图4.存储器框图5.单总线介绍6.单总线电路规范7.单总线时序结构8.DS18B20操作流程9.DS18B20数据帧 13.2DS18B20温度读取和温度报警器代码1.DS18B20温度读取(1)…...

ue 材质贴图Tiling repeat
材质问题,如下 贴图显然不符合逻辑,太大,并且是一次性贴图 换一个红砖纹理,就看清了,砖太大了 修改: 拖出一个TexCoord,代表坐标,拖出一个参数,代表次数,如…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...