赞
踩
在游戏开发过程中,我们会经常与数据打交道。很多时候,我们会为游戏对象配置数据,比如玩家初始生命值、属性等。那么就需要有个能够存储数据的东西来和游戏对象进行交互。而单机游戏一般都需要满足玩家的需求实现存档功能。
在这次的游戏开发中,我使用ScriptableObject实现多存档机制。
官方定义:一个类,如果需要创建无需附加到游戏对象的对象时,可从该类派生。它对仅用于存储数据的资源最有用。
官方定义不是那么的通俗易懂,这里在通俗的解释一下:首先ScriptableObject继承自 UnityEngine.Object,和MonoBehaviour的区别是,MonoBehaviour是以组件形式挂在GameObject上的,而ScriptableObject则以Assets资源的形式存在的,如果你需要存储数据,继承ScriptableObject类或许是更好的选择,因为ScriptableObject可以存储数据,模型,shader,材质等等。
可以看到 ScriptableObject 实例就是一种资源文件。它本身是个类,实例化之后得到的就是数据资源文件。
大体上可以分成三点:
1) 编辑模式下的数据持久化
2) 配置文件 (配置游戏中的数据)
3) 数据复用 (多个对象共用一套数据)
编辑模式下的数据持久化:
数据持久化:使用数据时从硬盘中读取,数据改变后保存到硬盘上,游戏退出后数据信息被存储到硬盘上,达到持久化的目的。
当我们在编辑模式下修改了继承自 ScriptableObject 对象的数据文件内容时,修改的数据将被保存到磁盘上。但是在发布运行后,即使在游戏中修改了 ScriptableObject 的数据,改后的数据并不会保存在本地,重新打开运行时数据并还是配置的初始数据。
因此 ScriptableObject 适合在编辑模式下调试数据,但不适合存储在游戏打包发布后的运行期间会改变的数据 。
配置文件: ScriptableObject非常适合用来做配置文件。因为:
1)配置文件的数据在游戏发布之前就定好了规则
2)配置文件的数据在游戏运行时只会读出来使用,不会修改数据的内容
3)传统的配置文件一般会通过xml、json、excel等方式来配置游戏数据
,相对来说都是在 Unity 外部通过其它格式的文件对数据进行配置。
而通过 ScriptableObject 我们可以直接在 Unity内部的 Inspector 面板中进行数据的配置,有时候会更加方便。
数据复用:对于只用不变的数据,通过使用 ScriptableObject 可以有效避免内存的浪费,因为它将共用的数据单独抽离出来,供相同的一类对象使用。
第8行,我们为其创建了Asset中的菜单选项,效果如下,我们可以看到此时SO_Datas中含有选项PlayerSaveData_SO,这正是我们在这里创建的。
上图是我们创建的PlaySaveData_SO,在这里我们可以为他直接修改属性。
在这次游戏中,我实现了三个存档。三个存档的数据分别存放在Save1,Save2,Save3。
我在这里实现的逻辑很简单,通过初始你点击进入的存档设立一个flag变量,如果是存档一对应flag=1,以此类推,根据flag的值选择是哪一个SaveData赋给TempSave,我们在之后的数据更新中就只用修改TempSave即可。
此处使用了MonoSingleTon单例模式,在其他地方可以直接用下图方式修改数据。
在Unity中,可以使用JsonUtility、XMLSerializer、BinaryFormatter等工具对对象进行序列化和反序列化。这也是一种专门的存储方式。同样,我们还可以通过数据库来存储。但是这些相对而言都没有ScriptableObject 这么方便。ScriptableObject 的使用可以非常直观的在检查器中查看和修改。这也是我权衡之下做出的选择。
下面使其他几种存储方式的使用场景。
1 可以把数据真正的存储到资源文件中.
这句话最好的示例就是在Unity
Editor运行的时候,常做一些运行时的修改,一般情况下如果直接在inspector面板修改一些数据,取消运行之后会直接清空你运行时修改的数据,这是很麻烦的,有经验的可能会Cope
Component values
复制当前数据。而使用ScriptableObject则可以在运行状态下动态的修改数据,取消运行之后也是运行时修改的数据。ScriptableObject而且还有一个inspector面板,可以很好的去操作,这里就体现到了ScriptableObject是一个assets,而MonoBehaviour这是以组件形式存在。
2 做数据分离
这里给出一个简单的实例,例如在发射子弹的时候,子弹身上是有控制子弹运动的脚本的,而每个武器子弹是不同的,每个不同的子弹身上有不同的数据,有相同的,也有不同的.如果去创建脚本,把每个子弹的一些数据写入到当前子弹的脚本身上,大量的数据让这个脚本去实现,会越来越臃肿,不易管理,而且很多数据可能在unity Editor不断的调试,对其策划是很困难的。如果把数据分离出来,去做成ScriptableObject脚本资源,而子弹脚本只需要去引用资源即可。
3 任务驱动型模块设计
任务驱动型模块设计是指在一些仿真类的开发中,经常遇到.一般在程序运行时,就在执行当前步骤所要完成的一些数据读取,资源的加载,数据的读取和资源的加载会分离到以ScriptableObject的assets的资源文件中,在执行每次任务的时候也是通过读取资源文件的形式。一般情况在大中型项目中会使用这种模块设计,而并不会以Res形式加载资源,因为配置资源表来的更加直观一些。
4 资源被实例化之后是被引用,而不是被复制
这一点其实说的就是MonoBehaviour痛点,每次实例化对象,都是完全复制,而非引用,对内存的消耗极大.而如果使用ScriptableObject实例化一次,他就会以资源的形式存储在asset文件中,其他地方如果使用的话直接引用就可以了.可以像Prefabs一样直接拖拽进去就可以了。
5 可以在场景中引用,共享,在项目之间共享.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。