推荐阅读

  • CSDN主页
  • GitHub开源地址
  • Unity3D插件分享
  • 简书地址
  • 我的个人博客
  • QQ群:1040082875

一、前言

有小伙伴跟我说,公司现在需要解析JSON,但是百度的解析JSON的又各种各样,我都看懵了,有没有好一点的解析方案,然后我就将我这篇文章推送给了他【Unity3D日常】Unity写Json数据,以及在Unity读取、解析Json数据。

过了一晚上,又跟我说,不行啊,虽然只要解析JSON了,但是步骤还是不太理解,怎么保存值呀,怎么赋值呀,都不会。

我说,那你把文档发给我,把需求跟我说一下,我整理一篇文章,让小伙们下次遇到这个问题知道总体流程了。

二、需求分析

需求

要从文档中读取所有的地铁线路和每条线路的站点,然后可以点击不同的线路切换显示不同的站点。

流程步骤

数据文档→读取数据→解析数据→保存数据

分析

(1)要有线路和站点的对应关系数据文档,这个已经有了:

(2)读取数据
读取数据没啥好说的,无论是json文件还是xml文件还是txt文件
使用File FileStream SteamReader StreamWriter 读取文件 都可以
每种写法都能百度出来

(3)解析数据
解析数据,方式也很多,以JSON为类,可以使用插件,也可以使用Unity自带的JSON解析类

插件:LitJSON解析、Newtonsoft.Json.dll

Unity自带解析JSON的类:JsonUtility

用那个都可以。

如果是txt数据,那么就要分析每一行的数据,如何切分,然后进行保存,比如:

1    1号线 103 苹果园
1   1号线 104 古城
1   1号线 105 八角游乐园
1   1号线 106 八宝山
1   1号线 107 玉泉路
1   1号线 108 五棵松
1   1号线 109 万寿路
1   1号线 110 公主坟
1   1号线 111 军事博物馆
1   1号线 112 木樨地
1   1号线 113 南礼士路

这段数据,最后是\r\n表示跳到下一行,中间以空格切分也就是\t

那么就可以先用\r\n切分每一行,然后用\t切换每一列,这样就将数据分析出来了。

(4)保存数据

最后一步,是保存,JSON解析完之后,需要保存到特定的跟JSON解析后匹配的类中,比如:

{"name":"小明","age":20,"interests":["sing","run"]
}

那么,解析的类也要有这几个值,而且要一一对应,不能有错,包括字母大小写:

[System.Serializable]
public class ModelTest
{public string name;public int age;public string[] interests;
}

那么,接收到的JSON数据怕生成类的时候出错怎么办,这时候就可以使用JSON数据转实体的功能:
https://www.json.cn/json/json2csharp.html

一键生成实体类,妈妈再也不用担心我出错了。

然后,用这个实体去接收解析好的JSON数据就可以了:

 ModelTest obj = JsonUtility.FromJson<ModelTest>(jsonTest);

jsonTest是JSON数据,ModelTest就是跟JSON数据匹配的实体。

那如果是txt一行一行读取的数据呢,比如:

1    1号线 103 苹果园
1   1号线 104 古城
1   1号线 105 八角游乐园
1   1号线 106 八宝山
1   1号线 107 玉泉路
1   1号线 108 五棵松
1   1号线 109 万寿路
1   1号线 110 公主坟
1   1号线 111 军事博物馆
1   1号线 112 木樨地
1   1号线 113 南礼士路

这个,就需要分析结构,然后使用数组或者List或者字典去保存了。

这个是一条地铁线,包含多个站点,每个站点有多个属性,可以使用自定义类,然后使用List去接收这个数据,比如:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class ReadData : MonoBehaviour
{List<StationInfo> Stations;void Start(){}
}public struct StationInfo
{public int lineid;          //线路编号public string linename;     //线路名称public string stationid;    //车站编号public string stationname;  //车站名称
}

三、实现

3-1 读取数据

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;public class ReadData : MonoBehaviour
{List<StationInfo> Stations;string Content;void Start(){//读取数据ReadFileData();}void ReadFileData(){string pathstations = Application.streamingAssetsPath + "/Stations_2018.txt";using (StreamReader SR = new StreamReader(pathstations)){//将所有的数据从文件以流形式保存到 ContentContent = SR.ReadToEnd();SR.Close();SR.Dispose();}}
}public struct StationInfo
{public int lineid;          //线路编号public string linename;     //线路名称public string stationid;    //车站编号public string stationname;  //车站名称
}

3-2 解析数据

 //解析数据 List<StationInfo> ParseStations(){if (!string.IsNullOrEmpty(Content)){List<StationInfo> info = new List<StationInfo>();string[] strarray = Content.Split(new char[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries);for (int i = 1; i < strarray.Length; i++){string[] Columns = strarray[i].Split(new char[] { '\t' }, System.StringSplitOptions.RemoveEmptyEntries);StationInfo stationInfo = new StationInfo();stationInfo.lineid = int.Parse(Columns[0]);stationInfo.linename = Columns[1];stationInfo.stationid = Columns[2];stationInfo.stationname = Columns[3];info.Add(stationInfo);}return info;}return null;}

3-3 保存数据

//保存数据
Stations = ParseStations();//线路编号  线路名称    车站编号    车站名称

完整代码:

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;public class ReadData : MonoBehaviour
{List<StationInfo> Stations;string Content;void Start(){//读取数据ReadFileData();}void ReadFileData(){string pathstations = Application.streamingAssetsPath + "/Stations_2018.txt";using (StreamReader SR = new StreamReader(pathstations)){//将所有的数据从文件以流形式保存到 ContentContent = SR.ReadToEnd();SR.Close();SR.Dispose();//保存数据Stations = ParseStations();//线路编号 线路名称    车站编号    车站名称}}//解析数据 List<StationInfo> ParseStations(){if (!string.IsNullOrEmpty(Content)){List<StationInfo> info = new List<StationInfo>();string[] strarray = Content.Split(new char[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries);for (int i = 1; i < strarray.Length; i++){string[] Columns = strarray[i].Split(new char[] { '\t' }, System.StringSplitOptions.RemoveEmptyEntries);StationInfo stationInfo = new StationInfo();stationInfo.lineid = int.Parse(Columns[0]);stationInfo.linename = Columns[1];stationInfo.stationid = Columns[2];stationInfo.stationname = Columns[3];info.Add(stationInfo);}return info;}return null;}
}public struct StationInfo
{public int lineid;          //线路编号public string linename;     //线路名称public string stationid;    //车站编号public string stationname;  //车站名称
}

3-4 生成地铁线

先摆个UI:

将这两个按钮分别做成预制体,命名为MetroLinePar、MetroSitePar,放到Resources文件夹下面:

编写代码:

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;public class ReadData : MonoBehaviour
{List<StationInfo> Stations;string Content;public GameObject MetroLinePanel;private GameObject MetroLinePar;public GameObject MetroSitePanel;private GameObject MetroSitePar;void Start(){//读取数据ReadFileData();MetroLinePar = Resources.Load<GameObject>("MetroLinePar");MetroLinePar = Resources.Load<GameObject>("MetroSitePar");//生成UICreateUI();}void CreateUI(){//找出所有地铁线Dictionary<int, string> MetroLine = new Dictionary<int, string>();for (int i = 0; i < Stations.Count; i++){if (!MetroLine.ContainsKey(Stations[i].lineid)){MetroLine.Add(Stations[i].lineid, Stations[i].linename);}}//生成地铁线foreach (var item in MetroLine){GameObject MetroLineItem = Instantiate(MetroLinePar, Vector3.zero, Quaternion.identity, MetroLinePanel.transform);MetroLineItem.GetComponentInChildren<Text>().text = item.Value;}}void ReadFileData(){string pathstations = Application.streamingAssetsPath + "/Stations_2018.txt";using (StreamReader SR = new StreamReader(pathstations)){//将所有的数据从文件以流形式保存到 ContentContent = SR.ReadToEnd();SR.Close();SR.Dispose();//保存数据Stations = ParseStations();//线路编号 线路名称    车站编号    车站名称}}//解析数据 List<StationInfo> ParseStations(){if (!string.IsNullOrEmpty(Content)){List<StationInfo> info = new List<StationInfo>();string[] strarray = Content.Split(new char[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries);for (int i = 1; i < strarray.Length; i++){string[] Columns = strarray[i].Split(new char[] { '\t' }, System.StringSplitOptions.RemoveEmptyEntries);StationInfo stationInfo = new StationInfo();stationInfo.lineid = int.Parse(Columns[0]);stationInfo.linename = Columns[1];stationInfo.stationid = Columns[2];stationInfo.stationname = Columns[3];info.Add(stationInfo);}return info;}return null;}
}public struct StationInfo
{public int lineid;          //线路编号public string linename;     //线路名称public string stationid;    //车站编号public string stationname;  //车站名称
}

运行:

所有的地铁线有,下面就需要将每条地铁线的每个站点对应起来。

3-5 生成站点

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;public class ReadData : MonoBehaviour
{List<StationInfo> Stations;string Content;public GameObject MetroLinePanel;private GameObject MetroLinePar;public GameObject MetroSitePanel;private GameObject MetroSitePar;void Start(){//读取数据ReadFileData();MetroLinePar = Resources.Load<GameObject>("MetroLinePar");MetroSitePar = Resources.Load<GameObject>("MetroSitePar");//生成UICreateMetroLine();}void CreateMetroLine(){//找出所有地铁线Dictionary<int, string> MetroLine = new Dictionary<int, string>();for (int i = 0; i < Stations.Count; i++){if (!MetroLine.ContainsKey(Stations[i].lineid)){MetroLine.Add(Stations[i].lineid, Stations[i].linename);}}//生成地铁线foreach (var item in MetroLine){GameObject MetroLineItem = Instantiate(MetroLinePar, Vector3.zero, Quaternion.identity, MetroLinePanel.transform);MetroLineItem.GetComponentInChildren<Text>().text = item.Value;//生成站点MetroLineItem.GetComponent<Button>().onClick.AddListener(()=> CreateMetroSite(item.Key));}}void CreateMetroSite(int _MetroLine){//找到传递过来的地铁线包含的所有站点List<StationInfo> MetroSite = new List<StationInfo>();for (int i = 0; i < Stations.Count; i++){if (Stations[i].lineid == _MetroLine){MetroSite.Add(Stations[i]);}}//清理原来的站点foreach (Transform transform in MetroSitePanel.transform){Destroy(transform.gameObject);}//生成站点foreach (var item in MetroSite){GameObject MetroLineSiteItem = Instantiate(MetroSitePar, Vector3.zero, Quaternion.identity, MetroSitePanel.transform);MetroLineSiteItem.GetComponentInChildren<Text>().text = item.stationname;}}void ReadFileData(){string pathstations = Application.streamingAssetsPath + "/Stations_2018.txt";using (StreamReader SR = new StreamReader(pathstations)){//将所有的数据从文件以流形式保存到 ContentContent = SR.ReadToEnd();SR.Close();SR.Dispose();//保存数据Stations = ParseStations();//线路编号  线路名称    车站编号    车站名称}}//解析数据 List<StationInfo> ParseStations(){if (!string.IsNullOrEmpty(Content)){List<StationInfo> info = new List<StationInfo>();string[] strarray = Content.Split(new char[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries);for (int i = 1; i < strarray.Length; i++){string[] Columns = strarray[i].Split(new char[] { '\t' }, System.StringSplitOptions.RemoveEmptyEntries);StationInfo stationInfo = new StationInfo();stationInfo.lineid = int.Parse(Columns[0]);stationInfo.linename = Columns[1];stationInfo.stationid = Columns[2];stationInfo.stationname = Columns[3];info.Add(stationInfo);}return info;}return null;}
}public struct StationInfo
{public int lineid;          //线路编号public string linename;     //线路名称public string stationid;    //车站编号public string stationname;  //车站名称
}

效果如图:


有两个小问题:
1)1号线显示两次,这是因为场景中的预制体没有隐藏

2)在生成的时候,让程序默认显示1号线的站点,这样合理一些。

void Start(){//读取数据ReadFileData();MetroLinePar = Resources.Load<GameObject>("MetroLinePar");MetroSitePar = Resources.Load<GameObject>("MetroSitePar");//生成UICreateMetroLine();//默认生成一号线的站点CreateMetroSite(1);}

效果图:

好,结束了。

四、后言

这个数据读取显示的整个步骤就完成了,万变不离其宗:

数据文档→读取数据→解析数据→保存数据→使用数据

明白了这几个步骤,剩下的难点就在于分析结构,然后如何保存数据,才能让自己去使用数据的时候方便一些。

比如,我想要保存所有的地铁线和地铁线的信息,那么就可以新建一个自定义类跟数据对应,然后使用List去保存数据,这样在后面的生成地铁线和地铁站点的时候就方便了许多。

这个实例演示的是如何从txt中读取数据,但是其他比如JSON、XML也是适用的,只是解析数据、保存数据的时候略微有些差别。

还有一点,就是List、字典、Resources、 StreamingAssets、Instantiate实例化,这些基本知识的运行要熟练。

【Unity3D日常开发】解析Txt文档,赋值给Text案例相关推荐

  1. java 检索编号输出信息_java,_java 如何解析txt文档,输入检索信息,然后输出,java - phpStudy...

    java 如何解析txt文档,输入检索信息,然后输出 请输入代码需求: 请解析config.txt,文件格式包括段落名称.字段名称和字段值.段落名称的值为:"segment:"右边 ...

  2. Python读取.txt文档内容/读取text文件内容

    Python读取.txt文档内容/读取text文件内容; 读取txt后缀文件的内容的两种方式,简约易懂,复制粘贴即可食用,节约你宝贵的时间 文档全部数据一次性读取 # -*- coding: UTF- ...

  3. 【Unity3D读取数据】(一)Txt文档操作(创建、读取、写入、修改)

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 QQ群:1040082875 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有 ...

  4. Unity3D操作数据之Txt文档操作(创建、读取、写入、修改)

    Unity3D操作数据之Txt文档操作(创建.读取.写入.修改) 一.前言 其实读取Txt文档非常简单.也不需要导入插件,仅需引入相应的命名空间即可. 命名空间:using System.IO 要注意 ...

  5. C++读取TXT文档,分行分段解析,通过UDP组播发送

    TXT文档格式 航点序号 经度° 纬度° 高度m 速度m/s 悬停时间s 标志字节 1 114.363945 38.056252 20 2 5 1 2 114.363697 38.055994 20 ...

  6. 【Unity3D日常开发】Unity3D中实现计时器工具类-正计时、倒计时、暂停计时、加速计时

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 QQ群:1040082875 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有 ...

  7. 【Unity3D日常开发】Unity3D打包PC窗口化打包设置

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 QQ群:1040082875 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有 ...

  8. 【Unity3D日常开发】Unity3D中打包WEBGL后读取本地文件数据

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 QQ群:1040082875 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有 ...

  9. Python爬虫实战,requests+openpyxl模块,爬取小说数据并保存txt文档(附源码)

    前言 今天给大家介绍的是Python爬取小说数据并保存txt文档,在这里给需要的小伙伴们代码,并且给出一点小心得. 首先是爬取之前应该尽可能伪装成浏览器而不被识别出来是爬虫,基本的是加请求头,但是这样 ...

最新文章

  1. 计算机控制系统在农业上的应用研究,智能控制仪表系统在农业电气自动化中的应用研究...
  2. 新信号!阿里 AI 工程师趋于年轻化,高端AI人才严重短缺
  3. Win32下内存分配简单示例 - 使用CFree
  4. 各种烧写文件格式简介-ELF Hex Bin axf
  5. linux的内置的账户_6 款面向 Linux 用户的开源绘图应用程序
  6. 研发管理三部曲——贰 · 研发管理应该干什么
  7. uuid.randomuuid()回重复么_【编译器玄学研究报告】第三期——“O0” 就能逃出优化的魔爪么?...
  8. Spring mvc mybatis cxf Add CGLIB to your classpath. 错误
  9. BGP(3):BGP 的路径优选
  10. C语言程序设计 数据类型 知识总结
  11. JTAG和SWD接口定义(20针)
  12. java实现两张图片合并起来。
  13. arm体系结构:arm920t
  14. linux中的last命令,linux系统中last命令的用法
  15. 六、Linux常用命令之压缩打包篇(gzip、gunzip、tar、zip、bzip2)
  16. cc150 java_javaMail 的邮件发送包括了抄送(CC),密送(BCC)采用springBoot
  17. 编写测试用例方法之错误推测法
  18. window10安装Mac虚拟机详细教程
  19. java基础篇(11) 枚举类型
  20. edge怎么开启沉浸式阅读_美人鼓上舞!端午小长假,豫园将开启史上首次沉浸式国风庙会...

热门文章

  1. 统计量与充分统计量的定义
  2. 通向沟通,通向分享!沟通无处不在,交流成就未来!
  3. 毕昇配置pytorch
  4. java学习第111天,p680-688(05/09)
  5. opencv null pointer (null name string) in cvNamedWindow
  6. [队内测试Day10.12]贪心+状压+分块+树状数组
  7. 必备的Web前端技术有哪些?
  8. 代码保护软件VMProtect用户手册主窗口之控制面板“项目”部分(4)
  9. COSCon’22第七届中国开源年会火热筹备中,第一波赞助伙伴已集结,一起上车共赴开源盛宴吧~...
  10. c语言结束程序符,c语句的结束符是什么