在Unity中使用Excel表开发单选题和多选题
前言:
去年还是小菜鸡的我写过在Unity中单选题和多选题的开发。现在进步一点点,这次可以直接编辑表格,在表格中增删改查数据即可,无需再对代码进行更改!
下载链接在文章末尾,需要的可以直接划到最后!
废话不多说,开始~
首先需要配置三个文件
- 读取表格的程序集:EPPlus
- 处理Json数据的程序集:Newtonsoft.Json
- 表格文件:question.xlsx
大概流程如下
创建StreamingAssets文件
首先我们在工程文件Assets文件下创建一个StreamingAssets(这里我们默认使用此路径为加载路径)
我们在此文件夹下创建一个表格。这里我使用的是.xlsx
下面是表结构,大家如果要修改的话,记得同时修改Question.cs哦!
创建Plugins文件
在Assets文件下创建一个名为Plugins文件夹
将刚才上面说了两个程序集EPPlus和Newtonsoft.Json放入此文件下
做完上面那些就可以导入我给大伙准备的脚本了
这里一共有三个脚本:
- ExcelMgr.cs
- Question.cs
- UIQuesPanel.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using OfficeOpenXml;
using System.IO;
using System.Data;
using System;
using Newtonsoft.Json.Linq;
using DialogEntity;namespace vvb_ExcelMgr
{public class ExcelMgr : MonoBehaviour{static ExcelPackage package;//表文件缓存public static ExcelWorkbook dialogWorkbook;//表工作簿public List<Question> questionList = new List<Question>();//题目缓存列表public string quesPackPath="question";//题目文件地址,文件后缀默认为".xlsx"private void Awake(){ReadExcel(quesPackPath, () =>{UIQuesPanel.quesList = GetQuesList(package);questionList = UIQuesPanel.quesList;//这里为了在inspecter中能看到读取到达数据});}/// <summary>/// 打开表缓存/// </summary>public static ExcelWorkbook ReadExcel(string excelPath, Action action){//Debug.Log(Application.streamingAssetsPath);excelPath = Application.streamingAssetsPath + "/"+excelPath+".xlsx";try{using (package = new ExcelPackage(new FileStream(excelPath, FileMode.Open))){action?.Invoke();return package.Workbook;}}catch (NullReferenceException e){Debug.LogError("空指针异常:" + e);return null;}catch (IOException e){Debug.LogError("文件打开异常:" + e);return null;}catch (Exception e){Debug.LogError("其他异常:" + e);return null;}}public List<Question> GetQuesList(ExcelPackage excelPackage){List<Question> quesList = new List<Question>();int dataStartRow = 0;if (excelPackage.Workbook.Worksheets.Count < 0){Debug.LogError("空表");return null;}ExcelWorksheet sheet = excelPackage.Workbook.Worksheets[1];for (int startRow = sheet.Dimension.Start.Row, endRow = sheet.Dimension.End.Row; startRow <= endRow; startRow++){if (sheet.GetValue(startRow, 1).ToString().Equals("quesId"))//此行开始才是咱们真正需要的数据,当然在开发过程中这里是不需要的{dataStartRow = startRow;break;}//Debug.Log(sheet.GetValue(startRow, 1).ToString());//Debug.Log(sheet.GetValue(2, 1).ToString());}for (int startRow = dataStartRow+1, endRow = sheet.Dimension.End.Row; startRow <= endRow; startRow++){JObject question = new JObject();//每一行实例化一个对象,用来存储到题目列表中for (int startColumn = sheet.Dimension.Start.Column, endColumn = sheet.Dimension.End.Column; startColumn <= endColumn; startColumn++){//这里要注意做一步特殊处理,因为当读取到选项内容那一行时,类型为数组,所以我们需要特殊处理一下if (startColumn == 3)//在表中我们将选项内容放在C列,也就是第三项。或者各位也可以使用其他的方式判定{JArray options = new JArray();string[] opsStr = sheet.GetValue(startRow, startColumn).ToString().Split(';');//这里先获取此处的字符串,然后再使用我们自定的符号切割以获得选项数组options.Add(opsStr);question.Add(sheet.GetValue(dataStartRow, startColumn).ToString(), options);}else{question.Add(sheet.GetValue(dataStartRow, startColumn).ToString(), sheet.GetValue(startRow, startColumn).ToString());}}quesList.Add(JsonUtility.FromJson<Question>(question.ToString()));//转成Question对象添加入列表中Debug.Log(question);}return quesList;}}
}
using System;
[Serializable]
public class Question
{public int quesId;//当前题号public string tittleStr;//题目内容public string[] optionsStr;//选项内容public int quesType;//题目类型public string ans;//正确答案public string analysis;//解析public int nextQuesId;//下一题号
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class UIQuesPanel : MonoBehaviour
{//为了方便,所有变量均拖拽赋值。public static List<Question> quesList = new List<Question>();public Text tittleTxt;//题目内容public RectTransform optionsRoot;//选项生成根节点public List<Toggle> optionTogList;//选项public ToggleGroup toggleGroup;//根节点togglegroup组件public GameObject togPrefab;//选项预制体public Text analysisTxt;//解析文本public Button lastBtn;//上一题按钮public Button nextBtn;//下一题按钮public Button confirmBtn;//确认作答按钮public int curQuesIndex = -1;//当前题索引private void Start(){_UIQuesPanelInit();}/// <summary>/// 上一题/// </summary>public void OnLastBtnClick(){curQuesIndex--;if (curQuesIndex <0){Debug.LogWarning("前面没有了!");curQuesIndex = 0;return;}_UpdateQues();}/// <summary>/// 下一题/// </summary>public void OnNextBtnClick()//这里加载下一题的方式也可以通过表中的字段nextQuesId,上一题同理(表中暂未设计)。{curQuesIndex++;if (curQuesIndex>quesList.Count-1){Debug.LogWarning("后面没有了!");curQuesIndex = quesList.Count-1;return;}_UpdateQues();}/// <summary>/// 刷新题目/// </summary>private void _UpdateQues(){analysisTxt.gameObject.SetActive(false);tittleTxt.text = (curQuesIndex + 1).ToString() + "." + quesList[curQuesIndex].tittleStr;int optionsCount = optionsRoot.childCount;optionTogList.Clear();while (optionsCount > 0){optionsCount--;Destroy(optionsRoot.GetChild(optionsCount).gameObject);}for (int i = 0; i < quesList[curQuesIndex].optionsStr.Length; i++)//根据选项个数创建相应的toggle数量{optionTogList.Add(Instantiate(togPrefab, optionsRoot).GetComponent<Toggle>());optionTogList[i].isOn = false;if (quesList[curQuesIndex].quesType == 0){optionTogList[i].group = toggleGroup;}optionTogList[i].GetComponentInChildren<Text>().text = quesList[curQuesIndex].optionsStr[i];}}/// <summary>/// 确认作答/// </summary>public void OnConfirmBtnClick(){if (curQuesIndex<0||curQuesIndex>quesList.Count-1){Debug.LogError("数组越界");return;}string selected=null;//用户选择analysisTxt.text = selected;analysisTxt.gameObject.SetActive(true);switch (quesList[curQuesIndex].quesType){case 0://单选for (int i = 0; i < optionTogList.Count; i++){if (optionTogList[i].isOn){selected = optionTogList[i].GetComponentInChildren<Text>().text[0].ToString();//默认第一个字符代表此选项,并与答案进行对比。这里正误判定也可以自己定义Debug.Log("选择的答案为:" + selected);break;}}break;case 1://多选for (int i = 0; i < optionTogList.Count; i++){if (optionTogList[i].isOn){selected += optionTogList[i].GetComponentInChildren<Text>().text[0].ToString();}}break;default:break;}if (string.IsNullOrEmpty(selected))//没作答情况。具体可以自定义,比如你弹出一个面板提示什么的,强制答完才行。{selected = "未作答";Debug.LogError("请先选择选项!");}if (selected.Equals(quesList[curQuesIndex].ans))//与正确答案做比较{Debug.Log("正确");analysisTxt.text = "<color=green>回答正确</color> ";}else{Debug.Log("错误");analysisTxt.text = "<color=red>回答错误</color> ";}analysisTxt.text += "你的答案:" + selected + " 正确答案:" + quesList[curQuesIndex].ans+"\n解析:" + quesList[curQuesIndex].analysis;}/// <summary>/// 面板初始化/// </summary>private void _UIQuesPanelInit(){//这里大伙儿可以自己默认调用一次“下一题”按钮的事件来默认更新第一道题。我就不写了analysisTxt.gameObject.SetActive(false);if (optionsRoot.gameObject.GetComponent<ToggleGroup>()){toggleGroup = optionsRoot.gameObject.GetComponent<ToggleGroup>();}else{toggleGroup = optionsRoot.gameObject.AddComponent<ToggleGroup>();}toggleGroup.allowSwitchOff = true;}
}
具体的过程我就不详述了,大伙儿看代码自行体会!
有何疑问欢迎留言讨论!需要源码的可以评论区留言或者私聊。
下面是源工程的下载地址:
链接:https://pan.baidu.com/s/1hrmtq9PGJlDg4Ya_YO6FeQ
提取码:grnh
在Unity中使用Excel表开发单选题和多选题相关推荐
- unity中解析excel表
上代码 using Excel; using System; using System.Collections; using System.Collections.Generic; using Sys ...
- vba mysql·教程_Excel VBA ADO SQL入门教程004:SQL中的Excel表
1. 上期我们聊了SQL常用查询语句中的字段查询,其简化版语法如下: SELECT 字段名 FROM 表名 当时我们说,FROM关键词指明了要获取字段信息的表的名称.倘若数据源是Excel表格,则需要 ...
- [Java中实现Excel表导入导出]基于easy-poi和EasyExcel两种方式实现
第一种:基于easy-poi实现Excel导入导出 1.导出Excel表格 第一步:在pom文件中导入依赖 <!--基于easy-poi实现Excel导入导出--><dependen ...
- Unity 中配置文件Excel 转xml ;josn;序列化ScriptableObject及加载(最详细)。
游戏中对策划的配置数据导入处理常用分为1.转xml或josn.2.序列化为ScriptableObject类.第一种方法游戏加载耗时一些,第二种避免了第一种方法加载缺点但内存要占用大一些.不过推荐第二 ...
- Unity中对Excel的操作(使用EPPlus)
目录 一.导入EPPlus 1.首先在Unity中导入EPPlus和Excel 2.创建脚本,引入命名空间 二.读取Excel 1. 获取Excel信息文件 2.打开Excel文件信息, ...
- django项目中实现excel表数据导入
依赖模块: xlrd模块安装:pip install xlrd 安装好xlrd模块之后基本的准备工作就已经完成. 实现: views.py: def import_excel(self, reques ...
- java代码中实现excel表下载
我这边定义了一个类Excel,然后定义了一个初始化方法 public class Ecxel { public static HSSFFont font; public static HSSF ...
- vue导入excel进度条_在vue中导入Excel表
使用的库js-xlsx 纯JS即可读取和导出excel的工具库https://github.com/SheetJS/js-xlsx 安装 直接下载dist目录下有很多个JS文件,一般情况下用xlsx. ...
- 将PPT中的excel表变成柱状图
如下表和图所示,那个更立体形象呢? 答案不言而喻. 第一步,做数据表 第二步,插入[图表] 点击确定后,会出现如下图: 你需要将前一页做的数据表,复制,粘贴到这个柱状图excel中 选择[匹配目标格式 ...
最新文章
- Spring_boot_pom.xml和启动方式
- 3 年经验的 Java 后端妹子,横扫阿里、滴滴、美团,整理出这份厚厚的 8000 字面经!...
- 老师吴恩达,身家又增20亿
- 开发日记-20190607 关键词 读书笔记《鸟哥的Linux私房菜-基础学习篇》
- 社交游戏纳入文化部监管视野 开发者或出海
- Java数据类型与各数据库类型对应一览表
- fzyzojP2291 -- 小添添的庄园之道路修复
- linux gfs原理,Linux GFS 配置方法及注意事项
- ruby学习笔记(3)--语法层面的先见之明
- Python 命令行之旅:深入 argparse(二)
- 协同多智能体学习的价值分解网络的原理与代码复现
- 3步教你学会cocos creator 物理引擎
- 10月最新720全景云系统,可生成小程序+带PC端+安装教程
- 使用ssh登录华为云linux,mac远程ssh登陆华为云--linux版本
- php fpm failed,ubuntu环境下启动php-fpm失败Job for php-fpm.service failed...
- AVplayer断网播放出错时player的duration、playableDuration、totalTime
- aws上创建eks集群
- CentOS7基于Hadoop 2.7.3安装Hive 2.1.1
- vue2 对接网易im初始化操作
- flash游戏地图编辑器
热门文章
- 大一高级计算机考试内容,大一计算机考试内容
- Crash自动修复系统
- 阿里云 windows 服务器卸载阿里云盾
- Spring Boot 2.2.x Junit4 升级为Junit5 后的变化、对比 找不到 org.junit.jupiter.api.Test
- HDMI接口的HPD问题
- phpadmin安装到mysql中,mysql 和phpadmin安装
- 最牛叉的街机游戏合集 模拟器
- Cosine Similarity 与 L2distanse
- Android UI自动化工具-SoloPi
- 基于Syntiant TinyML Board与Edge Impulse的LED语音控制(Arduino/C++)