很久没有总结做过的东西了,今天来小结一下最近两天做数据持久化的一些心得;所谓数据持久化简单来说,就是保存和加载。目前只做了切换场景时保存标记为持久化对象的单位的状态,等重新切换回来时,再加载;和退出游戏加载存档的机制是一样的。我选择使用了二进制存档的方式,思路大致如下:
1、给游戏对象的基类中加一个变量和一个guid的字符串
这里的Const.emptyGuid是存储的一个全局值,Guid.empty.ToString;
2、在基类或其派生类的面板工具中添加自动生成Guid的逻辑
生成Guid的代码也很简单
3、将ForceUpdateGuid设置成菜单功能,由于Guid无法被编辑,所以要做一个自动全部重新生成的功能。(因为不希望Guid被手动编辑,1来操作麻烦,2来防止误触,自动创建更能保证他的唯一性;这个自动创建最开始是打算在Awake时执行,但是后来还是打算做成菜单功能,担心Awake创建会有问题,具体啥问题没去想,总之自我感觉,在Awake里放执行逻辑要谨慎,特别是AlwaysExecute的组件,所以用菜单功能更能保证安全性,一次创建,永久保存)为了进一步保证工具的安全性(虽然现在只有我一个人在用)我加了一个提示框:
代码如下:
3、在场景加载时,更新游戏对象的状态,判定游戏对象的唯一性由persistStr决定。后面的逻辑都比较顺畅了,就不赘述了。
遇到的坑大致如下:
1、InstanceID不能保证对象唯一性,每次进出场景时值会发生变化,必须创建一个唯一标识的Guid
2、在编辑器中调用其target指向的类的方法要谨慎,有时候可能导致游戏运行的结果异常。
3、枚举enum和字典Dictionary不能被序列化(这里的序列化指C#的[Serializable]),使用二进制存档需要将数据分离出来一个可以被序列化的类中,所以要保证每个成员都能被序列化。将不能序列化的enum和Dictionary存储为可以被序列化的int和List,然后反序列化时再按照需要组装成需要的结构。
目前还有一些没有完善的地方,比如在3号地图打开通往1号地图的后门时,需要对1号地图的入口进行数据操作;至于为什么当初没有考虑将所有关卡设计为同一张地图,这个也是为了让关卡之间存在一定的独立性,不存在一个机制的出现,会出现牵一发而动全身的问题。虽然我把这款游戏定义为开放世界,但地图之间的独立性还会分开比较好,毕竟第一款游戏,不能在性能问题上出现败笔。