Unity加载配置文件的几种方式

从业以来,也做了有将近十款游戏了吧。其中各个游戏都需要去读取配置,无论这个配置是本地的还是从服务器获取的。而配置的读取方式有很多种,我自己也用过很多种,今天特地来总结一下各种读取方式的实现,以及它们的优缺点吧。

先来看看有哪几种常用的加载方式吧!

从本地数据库读取配置文件

  • 从Excel文件中读取配置文件
  • 从json文件中读取配置文件
  • 从xml文件中读取配置文件
  • 从csv文件中读取配置文件
  • 使用msgPack读取配置文件
  • 使用scriptableObject读取配置文件

别被这么多读取方式吓到,其实常用的也就那么一两种(json和msgPack),只要理解了你会发现它们并不复杂。当我们比较配置的读取方式时,我们实际上是在比较三件事:

  • 读取配置需要的时间
  • 配置所占用的存储空间
  • 配置的可读性

从Excel中读取配置

确实有游戏从excel中直接读取配置来供游戏使用,但这是个很不明智的选择。为什么这么说呢,我们来看一个对比:
一个包含三个表格的excel文件大小:36KB
在这里插入图片描述
上述表格转为json后的文件大小:10KB
在这里插入图片描述
就我个人而言,即使excel功能很强大,可读性很高,我还是无法忍受excel这么大的数据放到游戏中。所以我没有深入了解过这种读取方式,也不清楚它的读写速度。


从JSON中读取配置

我们先来看一段JSON文件吧:
Example - employees.json

[  
  {"no": 101, "name": "ruby", "age": 25, "gender": "female"},  
  {"no": 102, "name": "tom", "age": 30, "gender": "male"},  
  {"no": 103, "name": "rensanning", "age": 36, "gender": "male"}  
]  

很简单易读,一个企业的花名单。

json应该是目前最主流的,大家用的最多的方式之一了。因为json体积小,速度快,备受大家伙的宠爱。

至于怎么读取,我们可以使用litJson或者unity内置的JsonUtility类来完成序列化。关于JsonUtility的用法和局限性这篇文章讲的挺详细:(虽然排版不咋滴)
Unity JsonUtility的局限性
但有一点它没提到:JsonUtility无法解析带Bom头的json文件,否则会直接报错,导致游戏无法正常运行下去。具体什么报错,当时忘记记录了,好像是下面的错:

ArgumentException: JSON parse error: Invalid value.
UnityEngine.JsonUtility.FromJson[FakeInfo] (System.String json) (at /Users/builduser/buildslave/unity/build/artifacts/generated/common/modules/JSONSerialize/JsonUtilityBindings.gen.cs:25)
FakeInfo.CreateFromJSON (System.String jsonString) (at Assets/Resources/Scripts/FakeInfo.cs:11)
ContentContainerBuildContent+c__Iterator1.MoveNext () (at Assets/Resources/Scripts/ContentContainerBuildContent.cs:49)
UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) (at /Users/builduser/buildslave/unity/build/Runtime/Export/Coroutines.cs:17)

各位用的时候千万要注意。

嗯,json确实很强,读取速度和占用空间都很小。但是这世上没有十全十美的东西,json的可读性和可操作性完全比不上excel啊!毕竟excel可以写各种公式,可以被高手拿来做游戏。那咋办呢?回头去用臃肿的excel吗?

嗯…没错,我们还是要用excel。但这次我们并不直接去读取excel,而是把excel放在工程外部,当填好excel表格后,再通过特殊手段把excel转化为json存储在我们的工程中。这样时间、空间和可读性三全齐美,爽歪歪~

可问题是怎么转换呢?网上有很多方法,有的方法甚至可以直接生成对应的实体类。这里暂且不展开讲了。


从XML文件中读取配置

我们先来看一段XML文件:

  
  
    
    101  
    rensanning  
    36  
    male  
    
  
    
    102  
    tom  
    30  
    male  
    
  
    
    103  
    ruby  
    25  
    female  
    
  

可以观察到,它和json有点像,但是比json冗余了一点,因为它的每个字段都要有开始和结束标签。这也导致了它在时间和空间上的表现都略逊于json。所以还是推荐大家使用json。


从CSV中读取配置

CSV(Comma-Separated Values)逗号分隔值文件格式,有时也称为字符分隔值,因为分隔字符也可以不是逗号。其文件以纯文本形式存储表格数据(数字和文本)。

还是先来看一段示例吧:

no,name,age,gender  
101,rensanning,36,male  
102,tom,30,male  
103,ruby,25,female

同样是一段花名单,它和json相比更轻巧了,因为它只使用了逗号作为分隔符,没有任何多余的标签和定义。但这也带来了一个问题,当我们的字段中包含逗号怎么办?凉拌。

所以csv只适用于纯数字的配置文件,或者数据量大但是结构简单的配置文件。这种情况下,它的性能优于json。
而json可以适用于各种情况。


使用msgPack读取配置文件

这个是我今天和同学交流后,才知道的东西。三人行,并有我师。古人诚不欺我。

msgPack全称为messagePack。号称比json更小巧更快。就像它官网中所说:
Unity加载配置文件的几种方式_第1张图片
msg摒弃了json中的标识符,转而使用一些特殊的字节码来标识字段。将空间节省到了极致。如上图所示,同样内容msg比json节省了1/3的空间。

各位感兴趣的可以试下这个,很有潜力的东西。


使用scriptableObject读取配置文件

我们上面说了那么多,其实都是依赖外部的文件。这些文件本身无法被Unity识别,需要我们通过一些特定的API去读取、序列化它们。

那有没有Unity专用的存储配置格式呢?

Of course!万能的Unity已经为我们准备了scriptableObject。如图,这是一个可视化的持久化存储数据的容器:

Unity加载配置文件的几种方式_第2张图片
使用方法不多介绍,详见Unity官方手册。

这个方法的优点是可视化,在Unity内就能完成数据配置。同时,ScriptableObject本身就是Object的子类,调用起来很方便,不用像json那样需要我们解析完再组装。

但它也有缺点,如上图所示,那么多字段其实维护起来就比较费劲。更别提真正游戏中的配置文件动辄成本上千个字段。所以说它只适用于一些简单的配置,因为它的编辑灵活性远远不如excel。

最后再提一下注意事项:(好多人都被坑过)

ScriptableObject在真机上是不能被修改的!!!

这个ScriptableObject在真机上不可修改的,就像我们不可以在游戏运行时修改一个shader资源的代码、不可以修改一个纹理资源的像素内容一样,而在Unity Editor里可以修改ScriptableObject是因为Unity的编辑器对它格式的支持,就像使用vs code修改shader和使用ps修改一张纹理一样。


参考文档:
https://answers.unity.com/questions/844423/wwwtext-not-reading-utf-8-text.html
https://www.runoob.com/xml/xml-usage.html
xml,json未必是最好的数据传输方案,csv或许更适合
ScriptableObject 序列化

你可能感兴趣的:(Unity)