Unity使用BinaryFormatter保存自定义类列表时序列化报错如何解决
错误原因
BinaryFormatter序列化要求所有参与序列化的自定义类型都必须标记[System.Serializable]特性。你已为PlayerData添加了该特性,但PlayerData中存储的List<GunScript>的元素类型GunScript未标记可序列化,因此序列化触发报错。
如果GunScript是继承自MonoBehaviour的脚本,即使添加序列化特性也无法正常序列化,因为MonoBehaviour类型本身不支持BinaryFormatter的二进制序列化规则。
解决方案
情况1:GunScript为普通非MonoBehaviour类
直接给GunScript类添加[System.Serializable]特性即可:
[System.Serializable] public class GunScript { // 你原本的GunScript字段和逻辑 }
情况2:GunScript继承自MonoBehaviour(绝大多数情况)
不要直接序列化MonoBehaviour实例,单独定义纯数据类存储枪支需要持久化的属性,仅序列化纯数据类:
- 定义枪支纯数据类
[System.Serializable] public class GunSaveData { // 仅填写你需要保存的枪支属性,例如: public int gunId; public int damage; public int remainingBullet; public bool isUnlocked; }
- 修改
PlayerData中的列表类型
[System.Serializable] class PlayerData { public int money; public int xp; public float time; public int laval; public int maxXp; public int howMuchUpMaxXp; // 把List<GunScript>替换为纯数据类列表 public List<GunSaveData> gun = new List<GunSaveData>(); }
- 修改Save逻辑,把运行时的GunScript属性转存为纯数据
for (int i = 0; i < gun.Count; i++) { GunSaveData saveData = new GunSaveData(); // 从GunScript实例取出需要保存的属性赋值给saveData saveData.gunId = gun[i].gunId; saveData.damage = gun[i].damage; saveData.remainingBullet = gun[i].remainingBullet; saveData.isUnlocked = gun[i].isUnlocked; data.gun.Add(saveData); }
- Load完成后,把读取到的
GunSaveData列表属性赋值回场景中的GunScript实例即可。
额外优化建议
BinaryFormatter存在已知的安全漏洞,微软官方已不推荐使用,Unity项目中更推荐使用JsonUtility、Newtonsoft Json进行数据序列化,适配性更高、排查问题更简单。
内容的提问来源于stack exchange,提问作者יאיר מרקובסקי
相关产品推荐
相关产品推荐

