个人技术总结——Unity3D ScriptableObject实现多存档

文章目录

    • 一、概述
    • 二、详述
      • 2.1 什么是ScriptableObject?
      • 2.2 ScriptableObject 的主要作用
      • 2.3 ScriptableObject 的使用
      • 2.4 多存档的实现
    • 三、技术使用过程中遇到的问题和解决过程
      • 3.1 存储方式的选择
    • 四、总结
      • 关于使用ScriptableObject的优点和应用场景:
    • 参考文献

一、概述

在游戏开发过程中,我们会经常与数据打交道。很多时候,我们会为游戏对象配置数据,比如玩家初始生命值、属性等。那么就需要有个能够存储数据的东西来和游戏对象进行交互。而单机游戏一般都需要满足玩家的需求实现存档功能。
在这次的游戏开发中,我使用ScriptableObject实现多存档机制。

二、详述

2.1 什么是ScriptableObject?

官方定义:一个类,如果需要创建无需附加到游戏对象的对象时,可从该类派生。它对仅用于存储数据的资源最有用。

官方定义不是那么的通俗易懂,这里在通俗的解释一下:首先ScriptableObject继承自 UnityEngine.Object,和MonoBehaviour的区别是,MonoBehaviour是以组件形式挂在GameObject上的,而ScriptableObject则以Assets资源的形式存在的,如果你需要存储数据,继承ScriptableObject类或许是更好的选择,因为ScriptableObject可以存储数据,模型,shader,材质等等。
个人技术总结——Unity3D ScriptableObject实现多存档_第1张图片

可以看到 ScriptableObject 实例就是一种资源文件。它本身是个类,实例化之后得到的就是数据资源文件。

2.2 ScriptableObject 的主要作用

大体上可以分成三点:
1) 编辑模式下的数据持久化
2) 配置文件 (配置游戏中的数据)
3) 数据复用 (多个对象共用一套数据)

  • 编辑模式下的数据持久化:
    数据持久化:使用数据时从硬盘中读取,数据改变后保存到硬盘上,游戏退出后数据信息被存储到硬盘上,达到持久化的目的。
    当我们在编辑模式下修改了继承自 ScriptableObject 对象的数据文件内容时,修改的数据将被保存到磁盘上。但是在发布运行后,即使在游戏中修改了 ScriptableObject 的数据,改后的数据并不会保存在本地,重新打开运行时数据并还是配置的初始数据。
    因此 ScriptableObject 适合在编辑模式下调试数据,但不适合存储在游戏打包发布后的运行期间会改变的数据 。

  • 配置文件: ScriptableObject非常适合用来做配置文件。因为:
    1)配置文件的数据在游戏发布之前就定好了规则
    2)配置文件的数据在游戏运行时只会读出来使用,不会修改数据的内容
    3)传统的配置文件一般会通过xml、json、excel等方式来配置游戏数据
    ,相对来说都是在 Unity 外部通过其它格式的文件对数据进行配置。
    而通过 ScriptableObject 我们可以直接在 Unity内部的 Inspector 面板中进行数据的配置,有时候会更加方便。

  • 数据复用:对于只用不变的数据,通过使用 ScriptableObject 可以有效避免内存的浪费,因为它将共用的数据单独抽离出来,供相同的一类对象使用。

2.3 ScriptableObject 的使用

个人技术总结——Unity3D ScriptableObject实现多存档_第2张图片个人技术总结——Unity3D ScriptableObject实现多存档_第3张图片

第8行,我们为其创建了Asset中的菜单选项,效果如下,我们可以看到此时SO_Datas中含有选项PlayerSaveData_SO,这正是我们在这里创建的。
个人技术总结——Unity3D ScriptableObject实现多存档_第4张图片
个人技术总结——Unity3D ScriptableObject实现多存档_第5张图片
上图是我们创建的PlaySaveData_SO,在这里我们可以为他直接修改属性。

2.4 多存档的实现

在这次游戏中,我实现了三个存档。三个存档的数据分别存放在Save1,Save2,Save3。
个人技术总结——Unity3D ScriptableObject实现多存档_第6张图片
个人技术总结——Unity3D ScriptableObject实现多存档_第7张图片
个人技术总结——Unity3D ScriptableObject实现多存档_第8张图片
我在这里实现的逻辑很简单,通过初始你点击进入的存档设立一个flag变量,如果是存档一对应flag=1,以此类推,根据flag的值选择是哪一个SaveData赋给TempSave,我们在之后的数据更新中就只用修改TempSave即可。
此处使用了MonoSingleTon单例模式,在其他地方可以直接用下图方式修改数据。
个人技术总结——Unity3D ScriptableObject实现多存档_第9张图片

三、技术使用过程中遇到的问题和解决过程

3.1 存储方式的选择

在Unity中,可以使用JsonUtility、XMLSerializer、BinaryFormatter等工具对对象进行序列化和反序列化。这也是一种专门的存储方式。同样,我们还可以通过数据库来存储。但是这些相对而言都没有ScriptableObject 这么方便。ScriptableObject 的使用可以非常直观的在检查器中查看和修改。这也是我权衡之下做出的选择。
下面使其他几种存储方式的使用场景。
个人技术总结——Unity3D ScriptableObject实现多存档_第10张图片

四、总结

关于使用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 可以在场景中引用,共享,在项目之间共享.

参考文献

Unity存储游戏数据的几种方法
Unity进阶:ScriptableObject使用指南

你可能感兴趣的:(unity,游戏引擎)