[Unity3D daily development] Parse the Txt document and assign it to the Text case

Recommended reading

I. Introduction

A small partner told me that the company now needs to parse JSON, but Baidu's JSON parsing is of various kinds, I am confused, whether there is a better parsing solution, and then I pushed this article to me He [Unity3D Daily] Unity writes Json data, and reads and parses Json data in Unity .

After one night, I told me again, "No, I just need to parse the JSON, but I still don't understand the steps. How to save the value, how to assign it, I don't know how to do it.

I said, then you send me the document, tell me about the needs, and I will organize an article to let the guys know the overall process next time they encounter this problem.

2. Demand analysis

demand

To read all the subway lines and the stations of each line from the document, you can click on different lines to switch to display different stations.

Process steps

Data file→Read data→Analyze data→Save data

analysis

(1) There must be a data file corresponding to the line and the site. This is already there:

Insert picture description here


(2)
Reading the data There is nothing to say about reading the data, whether it is a json file, an xml file or a txt file,
use File FileStream SteamReader StreamWriter to read Files can be
written in Baidu

(3) Analyze data
There are many ways to parse data. Using JSON as the class, you can use plug-ins, or you can use Unity's own JSON parsing class

Plug-in: LitJSON parsing, Newtonsoft.Json.dll

Insert picture description here

Unity comes with a class for parsing JSON: JsonUtility can

Insert picture description here


use that.

If it is txt data, then it is necessary to analyze the data of each row, how to segment it, and then save it, such as:

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	南礼士路	

This piece of data, at the end \r\n means skip to the next line, separated by spaces in the middle, which is \t

Then you can use \r\n to split each row first, and then use \t to switch each column, so that the data can be analyzed.

(4) Save data

The last step is to save. After the JSON is parsed, it needs to be saved to a specific class that matches the JSON parsing, such as:

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

Then, the parsed class must have these values, and there must be a one-to-one correspondence, and there can be no mistakes, including letter case:

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

So, what should I do if the received JSON data is afraid of errors when generating the class? At this time, you can use the function of JSON data to entity:
https://www.json.cn/json/json2csharp.html

Insert picture description here


One-click to generate entity classes, mother Never worry about me making a mistake.

Then, use this entity to receive the parsed JSON data:

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

jsonTest is JSON data, and ModelTest is an entity that matches the JSON data.

What about the data read line by line in txt, such as:

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	南礼士路	

For this, you need to analyze the structure, and then use an array or List or dictionary to save it.

This is a subway line, containing multiple stations, each station has multiple attributes, you can use a custom class, and then use List to receive this data, such as:

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;  //车站名称
}

Three, realize

3-1 Read data

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))
        {
        	//将所有的数据从文件以流形式保存到 Content
            Content = SR.ReadToEnd();
            SR.Close();
            SR.Dispose();
        }
    }
}

public struct StationInfo
{
    public int lineid;          //线路编号
    public string linename;     //线路名称
    public string stationid;    //车站编号
    public string stationname;  //车站名称
}

3-2 Analyze the data

	//解析数据 
    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 Save data

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

Complete code:

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))
        {
            //将所有的数据从文件以流形式保存到 Content
            Content = 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 Generate subway line

First put a UI: make

Insert picture description here


these two buttons into prefabs, named MetroLinePar, MetroSitePar, and put them under the Resources folder:

Insert picture description here


write code:

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");

        //生成UI
        CreateUI();
    }
    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))
        {
            //将所有的数据从文件以流形式保存到 Content
            Content = 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;  //车站名称
}

Operation:

Insert picture description here


All subway lines are available, and each station of each subway line needs to be mapped to each other below.

3-5 Generate Site

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");

        //生成UI
        CreateMetroLine();
    }
    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))
        {
            //将所有的数据从文件以流形式保存到 Content
            Content = 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;  //车站名称
}

The effect is as follows:

Insert picture description here


There are two small problems:
1) Line 1 is displayed twice, because the prefab in the scene is not hidden.

Insert picture description here


2) When it is generated, let the program display the station of Line 1 by default, which is more reasonable.

void Start()
    {
        //读取数据
        ReadFileData();

        MetroLinePar = Resources.Load<GameObject>("MetroLinePar");
        MetroSitePar = Resources.Load<GameObject>("MetroSitePar");

        //生成UI
        CreateMetroLine();

        //默认生成一号线的站点
        CreateMetroSite(1);
    }

Effect picture:

Insert picture description here


Okay, it's over.

Four, afterword

The entire step of reading and displaying this data is completed, and it is inseparable from the original:

Data file→Read data→Analyze data→Save data→Use data

After understanding these steps, the remaining difficulty lies in analyzing the structure, and then how to save the data, so that it is more convenient for yourself to use the data.

For example, if I want to save the information of all subway lines and subway lines, I can create a new custom class corresponding to the data, and then use List to save the data, so that it will be convenient when generating subway lines and subway stations later. a lot of.

This example demonstrates how to read data from txt, but other things such as JSON and XML are also applicable, but there is a slight difference when parsing and saving data.

Another point is that List, Dictionary, Resources, StreamingAssets, Instantiate instantiation, the operation of these basic knowledge must be proficient.