问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Unity零基础教程:配置文件的读取、解析与使用

创作时间:
作者:
@小白创作中心

Unity零基础教程:配置文件的读取、解析与使用

引用
CSDN
1.
https://blog.csdn.net/weixin_45633843/article/details/144810952

本教程将带你学习如何在Unity中读取、解析和使用JSON配置文件。通过本教程,你将掌握如何在游戏中使用配置文件来管理游戏数据,这对于游戏开发来说是一个非常实用的技能。

一、读取配置的内容

在Assets文件夹中创建Configs文件夹用来保存配置文件。自行创建配置文件nodes.json,并复制以下内容到其中:

{
    "data": [
        {
            "ID": 1001,
            "Title": "紧锁的防盗门",
            "Type": 1,
            "ChildNode": [
                1002
            ],
            "Interact": 1011,
            "InteractType": 1,
            "InteractEffect": 2,
            "EffectValue": 1012,
            "Audio": 0,
            "Text": "你下班回到家,发现自己早上出门时忘记带钥匙了"
        },
        {
            "ID": 1002,
            "Title": "防盗窗",
            "Type": 0,
            "ChildNode": [
                1003
            ],
            "Interact": 1004,
            "InteractType": 1005,
            "InteractEffect": 1006,
            "EffectValue": 0,
            "Audio": 0,
            "Text": "你家的防盗窗,你试了试,只能把一只手伸进去"
        }
    ]
}

在scripts文件夹新建脚本文件,命名为jsonReader。想要让系统读取文件,首先要让系统知道文件的位置。创建变量用来存储配置文件路径(文件路径可以右键json文件,选择copy path复制得到),然后在Start方法里给变量赋值为文件路径:

public string jsonFilePath;
void Start()
{
    jsonFilePath = "Assets/Configs/nodes.json";
}

正常情况需要新建一个方法,用传参的方式读取不同类型的配置文件。本次教学的游戏只有一个配置文件,简单起见直接在Start方法里读取配置文件。首先用debug语句确认文件是否存在:

void Start()
{
    jsonFilePath = "Assets/Configs/nodes.json";//路径位置
    //确认位置是否存在
    if (File.Exists(jsonFilePath))//File.Exists方法填入路径后,如果文件存在,返回True,不存在返回False
    {
        Debug.Log("正确加载文件");
    }
    else
    {
        Debug.Log("路径配置错误");
    }
}

这里用到了Unity自带的File.Exists方法,该方法如果填入的路径找到配置文件,返回True,否则返回False。保存脚本,将脚本挂载到Canvas。运行测试得到控制台输出:

也可以尝试改写路径,给一个错误路径:

确认正确读取路径后,需要保存路径的内容。在Start中创建String类型变量dataJson,利用File.ReadAllText函数读取配置文件的内容并存储到变量中:

string dataJson = File.ReadAllText(jsonFilePath);

这时读取到的还只是字符串,系统无法理解具体的含义。接下来对配置文件的内容进行解析。

二、解析文件内容

打开配置可以看到,其中填写的是游戏内的节点信息,对应第一篇制作的配置表的内容。包含ID,标题,类型,子节点等等这些所有信息。

需要新建两个类,其中一个帮助系统理解每个节点有哪些内容,另一个类记录配置内共有多少节点。新建的类要在最外面一个{}外写,写在最后一个}后。这两个类需要对其序列化,序列化后的类可以存储数据,方便我们调用。在创建类的上一行补上[Serializable]标识。用tab补全代码,编译器会自动补库,在文件最上面声明要用到的库。

//创建一个类用来解析节点属性
[Serializable]
public class nodeVo
{
    public int ID;
    public string Title;
    public int Type;
    public List<int> ChildNode;//数组类型为List,内部存储子节点的ID,也就是int类型的变量
    public int Interact;
    public int InteractType;
    public int InteractEffect;
    public int EffectValue;
    public int Audio;
    public string Text;
}
//再建一个类用来解析配置内都有哪些节点
[Serializable]
public class nodeData
{
    public List<nodeVo> data;
}

代码如上,每个类前一行都要添加[Serializable]用来表明是序列化的类。

注意自定义的类的字段要和Json文件中的键一致,不然读不到数据。

使用这两个类,对数据进行解析。在start方法中,使用jsonUtility方法将json文件内容解析为对象。

在Start方法继续添加以下代码:

//使用jsonUtility方法将json文件解析为对象
nodeData nData = JsonUtility.FromJson<nodeData>(dataJson);
//创建一个词典,把配置放入词典中方便后续调用
Dictionary<int, nodeVo> nodesDic = new Dictionary<int, nodeVo>();
foreach (nodeVo innerObject in nData.data)//遍历nData内的所有数据
{
    nodesDic.Add(innerObject.ID, innerObject);//将nData内的所有数据,逐个放入字典
}

首先用类nodeData定义变量nData,并用JsonUtility读取dataJson中的文本,解析这些json文本为对象并赋值给nData完成初始化。

之后再创建一个字典nodesDic,其索引为int类型,内容为自定义类nodeVo类型,用来保存配置文件中的信息,方便后续的调用。

保存配置信息到字典时,采用foreach遍历,nData中的数据以nodeVo类型的列表存储,且定义为Data变量。所以foreach中使用nodeVo类型的变量innerObject来遍历nData中的Data列表。

每次循环将innerObject的ID对应赋值给字典的索引,将innerObject对应赋值给字典的内容。使用Add添加新的条目到字典。

三、使用配置

读取并解析配置后,下面演示如何使用他们。如果跟练了前面的内容,脚本Game的Start方法中存有语法教学相关的语句,暂时用不着,先全部删掉。

在Game脚本中声明一个全局字典变量:

public Dictionary<int, nodeVo> nodesDic = new Dictionary<int, nodeVo>();//声明字典用来存储JsonReader读取的配置信息

在JsonReader添加代码,为Game中创建的全局字典变量赋值:

//为Game中的全局变量赋值
transform.gameObject.GetComponent<Game>().nodesDic = nodesDic;

由于JsonReader和Game绑定在同一个Unity对象上,可以从这个对象上获取Game脚本,并为其全局变量nodesDic赋值。这样就将信息传递到了Game脚本处理。

回到Game脚本,接下来的目标是把节点当中的初始节点创建出来。配置中的Type为1时表示节点为初始节点。Type为0时表示节点为非初始节点。

在Start方法中使用foreach函数,遍历词典的内容,分辨并创建初始节点:

void Start()
{
    foreach (var node in nodesDic.Values) //遍历词典内的存储内容。声明局部变量时,使用 var 关键字可以让编译器从初始化表达式推断出变量的类型
    {
        if (node.Type == 1)//如果节点为初始节点
        {
            CreateNode(node.Title);//传递标题数据,来创建初始节点
        }
    }
}

其中,var关键字可以让编译器通过初始化表达式推断变量的类型。

这里本来应该能成功创建节点的,但是我没有创建成功。研究了半天,本来以为是字典的值没有传递,后来用Debug.Log排查,在JsonReader的赋值操作后面加上

Debug.Log(transform.gameObject.GetComponent<Game>().nodesDic.Values.Count);

Game的Start方法开头放上

Debug.Log(nodesDic.Values.Count);

这才发现是因为Game脚本在JsonReader之前激活了,而此时Game脚本里的字典还没有值。

默认情况下,最近创建的脚本执行的优先级应该高于之前创建的脚本,所以JsonReader会在Game之前执行。一般大家不会遇到这个情况。

解决这个问题的方法是让JsonReader在Game之前激活,为此需要修改两个脚本的优先级(在一般的项目中应该尽量用更好的初始化方式避免对脚本优先级顺序的操作,这里为了方便跟练,就不研究其他的方法了)。

在Edit→Project Settings...→Script Execution Order,点+号,将Game和JsonReader两个脚本加入,拖动JsonReader到Game上方,后面的优先级数字会自动调整。优先级数字越小,优先级越高。

调整完优先级后就可以正常生成节点了,可以说明我们之前的操作没有其他问题。可以把配置文件中1002节点的Type也修改为1,这样界面就会创建这两个节点。

这样,我们就可以通过配置来控制游戏中展示的内容了。

本篇学习了怎样读取配置,解析配置,并使用配置创建节点。下一篇会学习怎样通过点击节点来创建配置好的子节点。

本文原文来自CSDN

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号