设为首页收藏本站

微软Hololens全息现实网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

一键登录:

查看: 810|回复: 1

Unity教程 | 自制简易的游戏存档系统

[复制链接]
发表于 2017-7-10 15:26:24 | 显示全部楼层 |阅读模式

本文将为大家分享如何在Unity中实现简单的游戏存档系统,其中不会包含太多实际的代码,仅介绍在制作过程中需要考虑与解决的问题。该系统由一个学生团队为他们的首款商业游戏《Spirit》的原型开发,虽然简单,但其功能却很完善,也很容易扩展到其它需要保存状态的游戏中使用。   Unity提供了P...

本文将为大家分享如何在Unity中实现简单的游戏存档系统,其中不会包含太多实际的代码,仅介绍在制作过程中需要考虑与解决的问题。该系统由一个学生团队为他们的首款商业游戏《Spirit》的原型开发,虽然简单,但其功能却很完善,也很容易扩展到其它需要保存状态的游戏中使用。   Unity提供了PlayerPrefs来持久化保存游戏状态与数据,但不支持序列化Transform。C#也有大量的文件IO操作选项,但没有提供自动识别对象的方法。下面为大家介绍如何自定义永久性数据存储系统,首先编写一些简单的可序列化的数据结构来存储基本信息(如Transform等),将每个对象与其ID关联,然后将数据写入文件以供再次读取来恢复游戏状态。

7cbe5a8dc104303f3a915742b652c77f.jpg


第一步是选择生成对象ID的方法,基于创建时间生成的Hash值就很适合用作ID,但C#已经提供了GUID类可用于生成唯一的字符串: id = System.Guid.NewGuid().ToString(); 下面需要创建一个全局管理器类,来将ID与对应的对象进行关联。这个管理器就是一个单例类,带有几个用于查询键值的容器(C#中可能使用Dictionary结构)。还可以根据实际项目需求在Awake函数中添加一些基本的初始化与设置操作。如果有需要,还可以更新脚本执行顺序以确保管理器要先于ID生成脚本执行。另外,最好添加两个查找函数,一个用于将ID映射到实例ID(用于检查重复),另一个用于将ID直接映射到GameObject(用于加载文件时根据ID查找对象)。 ID脚本需要在对象创建时自动生成ID,并在运行期间保持不变。编写脚本时要注意以下几个关键点: 将ID定义为公共的String类型变了,以便Unity在保存并重新加载场景时,ID可以与对象一起被永久保存。可以利用Unity属性在检视视图中以只读方式显示变量值,以避免被误操作。如果ID为空或者无效,需要在Awake函数中生成ID并在管理器中注册此ID。在OnDestroy函数中从管理器中注销,以免后续遍历列表时出现空指针。 可以通过检测对象的实例ID与管理器中“记录”的自定义ID是否一致,来判断键值是否“有效”,以避免出现重复。如果不一致,就重新生成自定义ID。为什么这样呢?如果用ID实例化预制件,或是复制一个带有ID的GameObject,Unity也会复制原有的唯一ID,并且无法在Awake函数或其它地方分辨是否出现重复ID。而如果设置得当,管理器会在文件中记录ID,所以只要在查询函数中查看键值是否有效,就可以解决该问题。 最后,为ID脚本及管理器脚本添加[ExecuteInEditMode]标签,确保在编辑场景时脚本能正常运行。 正确设置好管理器与ID脚本后,只需简单地将ID脚本添加到任意需要识别并加载数据的对象上即可。为了节省空间,建议只为需要动态恢复的对象添加该脚本。

5de2d6311e38f5655a2f0b4caed97ba2.jpg


上图使用OGID脚本为对象设置了唯一的ID,Saveable脚本是另一个仅用作保存数据的脚本,它利用[System.Serializable]属性在内部构建数据结构来保存加载对象状态所需的数据,例如位置与方向等。 存储系统的其它部分就比较简单了,使用内置的路径变量与C#的文件函数,就可以轻松实现管理器。保存和加载数据是整个系统中最简单的部分,创建一些自定义类来存储对象的变换信息及其它数据,添加函数从GameObject读取数据或写入数据到GameObject,然后将脚本绑定到任意需要存档的对象上。此时可以选择使用自定义文件格式存储数据或直接使用[System.Serializable]属性进行标记,然后新建可序列化类包含自定义容器数组,在存储函数中复制数据容器的引用,使用下面的代码将数据保存到文件中:


System.IO.Stream s = new System.IO.FileStream(filepath, System.IO.FileMode.Create, System.IO.FileAccess.Write);System.Runtime.Serialization.IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();formatter.Serialize(s, saveGame);s.Close();

可以选择二进制或XML序列化对数据进行编码。但二者都有自己的长短处:二进制:文本文件不易阅读与编辑(对开发者不友好但能够预防玩家作弊),读写速度略快,相比之下数据较易损坏。XML:文本文件便于阅读与编辑,读写速度稍慢,文件出错时较易修复。 本例中采用的是二进制文件,因为它可以将对象保存为二进制字符串,或将二进制字符串还原为对象。



System.IO.Stream s = new System.IO.FileStream(filepath, System.IO.FileMode.Open, System.IO.FileAccess.Read);System.Runtime.Serialization.IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();SaveGame saveGame = (SaveGame) formatter.Deserialize(s);s.Close();

对保存的文件进行反序列化后,可以调用自定义函数将文件中的数据还原为GameObject(通过ID查找)。如果构建文件时遍历带有ID的对象,新对象会被自动保存到文件中。还可以修改代码来保存其它数据类型或调整文件管理器。

68c9f6a6f89b269f9020958c03385927.jpg


使用Unity自带的UGUI可以很方便的实现游戏截图、调整UI布局并创建存档菜单,并从存档中恢复游戏数据。这里存档信息显示了玩家名称与时间戳,以及玩家存档时的游戏截图。 结语本文介绍的只是Unity中实现文件存档的其中一点内容,文中的实现方式不一定适用于所有游戏,但其中介绍的思路与关键注意事项可以供大部分游戏参考。希望本文对大家有帮助,我们还会分享一些实际的游戏开发经验在Unity官方中文社区(unitychina.cn),请保持关注!

论坛(HoloLens全息现实网): http://hololens8.cn

VR/AR/HoloLens开发者QQ群:220104582
VR/AR资源分享QQ群:281921834
HoloLens/VR/AR交流QQ群:433190386






上一篇:关于hololens如何扫描房间信息
下一篇:巧用Shader,游戏玩法新思路
发表于 2017-7-10 16:16:35 | 显示全部楼层
酱紫啊,涨姿势啦。。
*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

注册验证邮件查收提醒:

由于各大邮箱政策原因,

如果没收到邮件提醒,

您的注册验证邮件可能

被投送到您邮箱的垃圾箱,

请注意查收验证哦


QQ|小黑屋|Hololens全息现实网 ( 京ICP备15026232号   点击这里给我发消息

GMT+8, 2018-11-21 06:34 , Processed in 0.632324 second(s), 30 queries .

Powered by Hololens全息现实网 X3.2

© 2001-2017 Hololens全息现实网

快速回复 返回顶部 返回列表