在游戏开发中,必定会有数据编辑、保存和读取。需要兼顾开发效率、运行效率和兼容性
。
数据的显示、编辑
unity的内置序列化还是比较好用的,所见即所得,但有个比较蛋疼的地方,不支持接口、多态对象
。在设计数据结构的时候,如果没有多态,将会有很多数据冗余。。。
在unity2020版本中,多了一个SerializeReference
特性,可以帮助我们显示多态数据,但也有个比较蛋疼的地方,它只能显示,不能编辑,你说艹蛋不艹蛋🙄,做功能只做一半之unity。
这里,我们使用Odin插件。如果没有Odin,可以考虑UnitySerializedReferenceUI。有了上面的基础,就可以在编辑器下快速创建、删除多态对象了!
不使用多态
public class data
{
// event id
public uint id;
// animation event parameter
public string animationName;
// sound event parameter
public string soundName;
// more and more...
}
public class table
{
public List<data> datas;
}
动画事件只会用到animationName,声音事件只会用到soundName,但每个data都包含了其他无用字段,这真是太。。。
如果在unityeditor下编辑,还得根据事件类型做switch case,只在面板中只曝露出有用的参数。。。不然。。。
如果采用json、xml之类自动化的方式来保存,那无用的参数就全进文本了。。。手写parser?那慢慢写吧。。。
使用多态
public abstract class data
{
// event id
public uint id;
}
public class animation_data : data
{
// animation event parameter
public string animationName;
}
public class sound_data : data
{
// sound event parameter
public string soundName;
}
// more and more...
public class table
{
public List<data> datas;
}
这样数据结构看起来就清晰多了,而且不会存储不必要的东西!文件大小、内存大小都会降低!也不用编写又臭又长的编辑器代码和序列化代码!
数据的读写
处理了显示、编辑的问题,另一个问题就是编辑器读取,以及运行时读写的问题了,不过一般运行时只考虑读。
序列化库可以先选用 json.net 或者 protobuf.net,都支持多态序列化。
数据的读写有个问题,我们可能在开发过程中修改数据结构,可能有以下几种问题:
- 字段名改变
- 基元类型改变,如,int->string
- 容器类型改变,如,list->dictionary
- 数据结构类改版,如,classA包含a、b、c,现要改为classA包含classB,classB包含a、b、c
出现上述问题后,plan A,手动检查,重新弄。策划:头伸过来,我给你加个buff。哈哈哈~
plan B,使用序列化库解决:
- 字段名改变
protobuf使用int作为key,仅改变字段名,没有任何影响。
json.net则使用JsonProperty即可指定名称,类似unity的SerializeAs。 - 剩下所有,可以考虑如下方案
被(ProtoAfterDeserializaton、ProtoBeforeDeserializaton)、(OnSerializing、OnDeserialized)
等特性标记的方法可以在对应时机的被反射调用,所以利用这个,我们可以编写兼容代码,来最大化保证数据的兼容性!
坑点
Q: SerializeReference 在类名修改后,可能会出现报错,且编辑器下ScriptableObject无法保存。
A1: 由于我们是序列化成自己的数据文件了,则可以删掉后,再重新生成ScriptableObject。
A2: 添加 [MovedFrom(false, “OldNameSpaceName”, “OldAssemblyName”, “OldClassName”)] 特性也可以解决。
结论
有了以上基础,即可在unity里编辑逻辑数据,从了避免在excel里抽象数据结构了。