关于Unity ScriptableObject 的数据保存问题

最近在开发的时候遇到的问题:在用ScriptableObject进行保存数据的时候,并不是所有的数据都能正常保存,这让人很是难受。所以我决定系统性地整理一下这个问题:

 

注:建议大家将自己的Unity文件保存方式设置为Text而不是二进制,这样用记事本打开保存的Assest文件就能明码查看内容。可以清楚地看见自己哪些数据保存了,而哪些没有。

可以通过上述方式再查看自己是否是用文本方式再保存文件;

 

哪些类型的数据能直接保存?

首先,单纯的String、Bool 、Int之类的值都是能正常保存的。

引用的脚本、预制、资源当然也是能直接保存的。(他们会转换成文件ID)

然后是一些数据容器:

列表、数组(仅限一维数组)是可以直接保存的。

至于类,当然是要设置为可序列化才能保存(System.Serializable)。

 

哪些不能直接保存?

其实这个才是关键的地方:二维数组、字典是不能直接保存的

不论你在属性面板如何编辑,在脚本里面如何添加代码,二维数组和字典都是不能保存进Assest的。

需要注意的是,如果你用了Odin插件,或者你自己实现了二维数组/字典在属性面板上的显示方法,你自然是可以编辑的,但是并不一定能保存!

这里插句嘴,说下Odin插件。Odin Inspector可以序列化字典,但是在跨平台时这个字典未必能读出来。这种时候需要编写他的AOT Genteration,详见 : https://blog.youkuaiyun.com/cyf649669121/article/details/111795715 。

可能是Unity没有像字典这种键值对,或者多维数组的保存方式吧……反正这种类型就是不会保存成功的,切记!

 

解决方案:

其实也没啥好的解决方案,他本身不能保存,只有将其装换成能保存的类型。

例如字典,只能让他变成列表。你可以一列存键,一列存值,或者干脆放一起也可以。

至于二维数组,也是类似的方法:存一个大小,然后把值转成一维数组存下来。

 

 

虽然用蛋疼的方式解决了,我还是觉得这个ScriptableObject的保存机制很坑。当然也有可能是我没有找到正确的API导致的,如果有大佬知道更方便的办法、能直接保存的方法,欢迎留言告诉我~~

━(*`∀´*)ノ亻!

 

### Unity ScriptableObject 使用教程和最佳实践 #### 创建 ScriptableObject 资源 ScriptableObject 提供了一种创建可重用的数据容器的方法,这些数据可以在多个场景之间共享而不会丢失。为了创建一个新的 ScriptableObject 类型,在项目中定义一个继承自 `ScriptableObject` 的类。 ```csharp using UnityEngine; [CreateAssetMenu(fileName = "NewGameData", menuName = "Game/NewGameData")] public class GameData : ScriptableObject { public string playerName; public int playerLevel; } ``` 此代码片段展示了如何声明一个名为 `GameData` 的新 ScriptableObject[^1]。 #### 实例化 ScriptableObject 对象 一旦有了 ScriptableObject 类型之后,就可以通过右键点击 Project 视图中的 Assets 文件夹并选择 Create -> Game -> NewGameData 来实例化该类型的对象。这将在资源管理器中生成一个新的资产文件,其中包含了默认初始化后的字段值。 #### 加载与保存 ScriptableObject 数据 当需要加载已存在的 ScriptableObject 或者想要修改其属性时,可以通过 AssetDatabase API 获取对它的引用: ```csharp // 假设有一个已经存在于 Resources 文件夹下的 ScriptableObject 名为 gameData.asset string path = "Assets/Resources/gameData.asset"; GameData loadedData = (GameData)AssetDatabase.LoadAssetAtPath(path, typeof(GameData)); if(loadedData != null){ Debug.Log($"Player Name: {loadedData.playerName}, Level: {loadedData.playerLevel}"); } else { Debug.LogError("Failed to load data"); } // 修改 ScriptableObject 属性后记得调用 EditorUtility.SetDirty() 方法标记更改 EditorUtility.SetDirty(loadedData); ``` 这段脚本说明了怎样读取存储于磁盘上的特定路径处的 ScriptableObject,并打印出玩家的名字以及等级;同时也提到了在改变 ScriptableObject 中的信息以后要做的工作——通知 Unity 这些改动应该被持久化下来[^2]。 #### 将 Excel 表格转化为 ScriptableObject 对于那些习惯使用电子表格来整理游戏配置的人来说,可以考虑利用像 **Unity-Excel-Importer** 插件这样的工具将 .xls 或者 .xlsx 文件里的内容映射成相应的 ScriptableObject 结构体。这样不仅提高了工作效率还减少了手动输入可能带来的错误风险[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值