【unity小技巧】unity读excel配置表操作,excel转txt文本,并读取txt文本内容,实例说明

文章目录

前言

关于unity读excel配置表操作,其实之前就有用过,这里只是单独整理出这部分知识,后续好使用。

感兴趣可以去看看:【用unity实现100个游戏之7】从零开始制作一个仿杀戮尖塔卡牌回合制游戏(附项目源码)

下载资源库

读取Excel需要用到Excel.dllICSharpCode.SharpZipLib库文件

这里我把两个库都放在百度云了,大家可以自行去下载

链接:https://pan.baidu.com/s/1iM-E5TSAxtlWOAhMmWy1ZQ?pwd=s8o4

提取码:s8o4

导入资源库

将前面下载的这两个dll库放进项目即可

excel转txt文本

新建MyEditor.cs放在Editor目录下

MyEditor.cs代码

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;//编辑器的命名空间
using System.IO;//文件流
using Excel;//读取excel
using System.Data;

//编辑器脚本
public static class MyEditor
{
    [MenuItem("我的工具/excel转成txt")]
    public static void ExportExcelToTxt()
    {
        //_Excel文件夹路径
        string assetPath = Application.dataPath + "/_Excel";
        //获得Excel文件夹中的excel文件
        string[] files = Directory.GetFiles(assetPath, "*.xlsx");
        for (int i = 0; i < files.Length; i++)
        {
            files[i] = files[i].Replace('\\', '/');//反斜杠替换成正斜杠
            //通过文件流读取文件
            using (FileStream fs = File.Open(files[i], FileMode.Open, FileAccess.Read))
            {
                //文件流转成excel 对象
                var excelDataReader = ExcelReaderFactory.CreateOpenXmlReader(fs);
                //获得excel数据
                DataSet dataSet = excelDataReader.AsDataSet();
                //读取excel第一张表
                DataTable table = dataSet.Tables[0];
                //将表中内容 读取后 存储到 对应的txt文件
                readTableToTxt(files[i], table);
            }
        }
        //刷新编辑器
        AssetDatabase.Refresh();
    }

    private static void readTableToTxt(string filePath, DataTable table)
    {
        // 获得文件名(不要文件后缀 生成与之名字相同的txt文件)
        string fileName = Path.GetFileNameWithoutExtension(filePath);
        // txt文件存储的路径
        string path = Application.dataPath + "/Resources/Data/" + fileName + ".txt";
        //判断Resources/Data文件夹中是否已经存在对应的txt文件,如果是 则删除
        if (File.Exists(path))
        {
            File.Delete(path);
        }
        // 文件流创建txt文件
        using (FileStream fs = new FileStream(path, FileMode.Create))
        {
            // 文件流转写入流方便写入字符串
            using (StreamWriter sw = new StreamWriter(fs))
            {
                // 遍历table
                for (int row = 0; row < table.Rows.Count; row++)
                {
                    DataRow dataRow = table.Rows[row];
                    string str = "";
                    //遍历列
                    for (int col = 0; col < table.Columns.Count; col++)
                    {
                        string val = dataRow[col].ToString();
                        str = str + val + "\t";//每一项tab分割
                    }

                    //写入
                    sw.Write(str);

                    //如果不是最后一行换行
                    if (row != table.Rows.Count - 1)
                    {
                        sw.WriteLine();
                    }
                }
            }


        }
    }
}

记得在Resources目录下新建Data文件夹用来存放生成的txt文本,我们的xlsx配置表信息就放在_Excel文件夹下,点击我的工具->excel转成txt,会将_Excel文件夹里的xlsx文件生成为txt保存到/Resources/Data/目录下

配置表大概样式

card.xlsx

转为txt后内容如下

读取txt内容

新增GameConfigData,定义读取配置表类

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 游戏配置表类,每个对象对应一个xt配置表
public class GameConfigData
{
    // 存储配置表中的所有数据
    private List<Dictionary<string, string>> dataDic;
    // 构造函数,参数为字符串
    public GameConfigData(string str)
    {
        // 初始化数据字典
        dataDic = new List<Dictionary<string, string>>();
        // 按换行符切割字符串
        string[] lines = str.Split('\n');
        // 第一行是存储数据的类型
        string[] title = lines[0].Trim().Split('\t');//tab切割
        // 从第三行(下标为2)开始遍历数据,第二行数据是解释说明
        for (int i = 2; i < lines.Length; i++)
        {
            // 创建新的字典存储每行数据
            Dictionary<string, string> dic = new Dictionary<string, string>();
            // 按tab切割每行数据
            string[] tempArr = lines[i].Trim().Split("\t");
            // 将切割后的数据添加到字典中
            for (int j = 0; j < tempArr.Length; j++)
            {
                dic.Add(title[j], tempArr[j]);
            }
            // 将字典添加到数据列表中
            dataDic.Add(dic);
        }
    }

    // 获取所有行的数据
    public List<Dictionary<string, string>> GetLines()
    {
        return dataDic;
    }

    // 根据ID获取一行数据
    public Dictionary<string, string> GetOneById(string id)
    {
        // 遍历数据列表
        for (int i = 0; i < dataDic.Count; i++)
        {
            // 获取当前字典
            Dictionary<string, string> dic = dataDic[i];
            // 如果字典中的ID与参数相同,返回该字典
            if (dic["Id"] == id)
            {
                return dic;
            }
        }
        // 如果没有找到,返回null
        return null;
    }
}

新增GameConfigManager.cs,读取不同配置表信息配置

csharp 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
// 游戏配置管理类
public class GameConfigManager
{
    // 单例模式
    public static GameConfigManager Instance = new GameConfigManager();
    private GameConfigData cardData;//卡牌表
    private GameConfigData enemyData;//敌人表
    private GameConfigData levelData;//关卡表
    private GameConfigData cardTypeData; //卡牌类型
    // 文本资源
    private TextAsset textAsset;

    // 初始化配置文件(txt文件 存储到内存)
    public void Init()
    {
        // 加载卡牌数据
        textAsset = Resources.Load<TextAsset>("Data/card");
        cardData = new GameConfigData(textAsset.text);

        // 加载敌人数据
        textAsset = Resources.Load<TextAsset>("Data/enemy");
        enemyData = new GameConfigData(textAsset.text);

        // 加载关卡数据
        textAsset = Resources.Load<TextAsset>("Data/level");
        levelData = new GameConfigData(textAsset.text);

        //卡牌类型数据
        textAsset = Resources.Load<TextAsset>("Data/cardType");
        cardTypeData = new GameConfigData(textAsset.text);
    }

    // 获取卡牌行数据
    public List<Dictionary<string, string>> GetCardLines()
    {
        return cardData.GetLines();
    }

    // 获取敌人行数据
    public List<Dictionary<string, string>> GetEnemyLines()
    {
        return enemyData.GetLines();
    }

    // 获取关卡行数据
    public List<Dictionary<string, string>> GetLevelLines()
    {
        
        return levelData.GetLines();
    }
    // 根据ID获取卡牌数据
    public Dictionary<string, string> GetCardById(string id)
    {
        return cardData.GetOneById(id);
    }
    // 根据ID获取敌人数据
    public Dictionary<string, string> GetEnemyById(string id)
    {
        return enemyData.GetOneById(id);
    }
    // 根据ID获取关卡数据
    public Dictionary<string, string> GetLevelById(string id)
    {
        return levelData.GetOneById(id);
    }

    //根据ID获取卡牌类型
    public Dictionary<string, string> GetCardTypeById(string id)
    {
        return cardTypeData.GetOneById(id);
    }
}

调用测试

csharp 复制代码
//初始化配置表
GameConfigManager.Instance.Init();

//测试
string name = GameConfigManager.Instance.GetCardById("1001")["Name"];
print(name);

运行效果,输出正确

读取配置表所有的数据,并使用

比如配置表大概样式

level.xlsx

转换为txt文本后效果

GameConfigManager代码如下

sql 复制代码
using System.Collections.Generic;
using UnityEngine;

// 游戏配置管理类
public class GameConfigManager
{
    public static GameConfigManager Instance = new GameConfigManager();
    
    private GameConfigData levelData;//关卡数据

    // 文本资源
    private TextAsset textAsset;

    // 初始化配置文件(txt文件 存储到内存)
    public void Init()
    {
        // 加载关卡数据
        textAsset = Resources.Load<TextAsset>("Data/level");
        levelData = new GameConfigData(textAsset.text);
    }

    // 获取关卡行数据
    public List<Dictionary<string, string>> GetLevelLines()
    {
        return levelData.GetLines();
    }

    // 根据ID获取关卡数据
    public Dictionary<string, string> GetLevelById(string id)
    {
        return levelData.GetOneById(id);
    }
}

新增GenerateZombies 调用配置表信息并使用

sql 复制代码
using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using Unity.VisualScripting;
using UnityEngine;

public class GenerateZombies : MonoBehaviour
{
    public static GenerateZombies Instance { get; private set; }
    public GameObject zombiePrefab; //僵尸预制体

    public int curLevelId = 1; //当前关卡
    public int curProgressId = 1;//当前进度
    public List<GameObject> curProgressZombie;//保存当前进度的敌人
    int zOrderIndex = 0;//排序

    private void Awake()
    {
        Instance = this;
    }

    private void Start()
    {
        curProgressZombie = new List<GameObject>();
        //初始化配置表
        GameConfigManager.Instance.Init(); 
        TableCreateZombie();
    }

    //生成僵尸
    private void TableCreateZombie()
    {
        //判断是否是最后一波敌人,如果表格中当前进度没有可以创建的敌人,及游戏胜利
        bool canCreate = false;
  
        //获取关卡行数据
        List<Dictionary<string, string>> listData = GameConfigManager.Instance.GetEnemyLines();
        listData.ForEach(data =>
        {
            //属于当前关卡的僵尸
            if (data["levelID"] == curLevelId.ToString() && data["progressId"] == curProgressId.ToString())
            {
                //延迟一段时间创建僵尸
                StartCoroutine(ITableCreateZombie(data));
                //代表当前进度有敌人
                canCreate = true;
            }
        });

        if(!canCreate){
            StopAllCoroutines();//停止所有的携程
            //TODO:游戏胜利处理
            Debug.Log("游戏胜利");
        }
    }

    IEnumerator ITableCreateZombie(Dictionary<string, string> levelItem)
    {
        yield return new WaitForSeconds(float.Parse(levelItem["createTime"]));

        //加载预制件:从Resources文件夹中加载,例如Zombie1
        GameObject zombiePrefab = Resources.Load("Prefabs/Zombie" + levelItem["zombieType"]) as GameObject;

        //生成僵尸实例
        GameObject zombie = Instantiate(zombiePrefab);

        //根据配表的生成位置,找到父物体
        Transform zombieLine = transform.GetChild(int.Parse(levelItem["bornPos"]));
        zombie.transform.parent = zombieLine;
        zombie.transform.localPosition = Vector3.zero;
        zombie.GetComponent<SpriteRenderer>().sortingOrder = zOrderIndex;
        zOrderIndex ++;
        
        curProgressZombie.Add(zombie);
    }

    //消灭敌人
    public void ZombieDied(GameObject gameObject){
        if(curProgressZombie.Contains(gameObject)){
            curProgressZombie.Remove(gameObject);
        }
        //当前进度的僵尸全部消灭了,开启下一个进度
        if(curProgressZombie.Count == 0){
            curProgressId += 1;
            TableCreateZombie();
        }
    }
}

消灭敌人时调用,控制游戏进度变化

sql 复制代码
GenerateZombies.Instance.ZombieDied(gameObject);

效果

稍后补充

结束语

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,最近开始自学unity,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!php是工作,unity是生活!如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~

相关推荐
在下不上天几秒前
Flume日志采集系统的部署,实现flume负载均衡,flume故障恢复
大数据·开发语言·python
陌小呆^O^14 分钟前
Cmakelist.txt之win-c-udp-client
c语言·开发语言·udp
I_Am_Me_30 分钟前
【JavaEE进阶】 JavaScript
开发语言·javascript·ecmascript
重生之我是数学王子40 分钟前
QT基础 编码问题 定时器 事件 绘图事件 keyPressEvent QT5.12.3环境 C++实现
开发语言·c++·qt
Ai 编码助手41 分钟前
使用php和Xunsearch提升音乐网站的歌曲搜索效果
开发语言·php
学习前端的小z1 小时前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
星星会笑滴1 小时前
vue+node+Express+xlsx+emements-plus实现导入excel,并且将数据保存到数据库
vue.js·excel·express
神仙别闹1 小时前
基于C#和Sql Server 2008实现的(WinForm)订单生成系统
开发语言·c#
XINGTECODE1 小时前
海盗王集成网关和商城服务端功能golang版
开发语言·后端·golang
zwjapple1 小时前
typescript里面正则的使用
开发语言·javascript·正则表达式