使用BinaryFormatter保存行星数据时触发Vector3序列化异常
解决Unity BinaryFormatter序列化Vector3的SerializationException问题
核心问题原因
Unity内置的UnityEngine.Vector3未标记符合.NET要求的[Serializable]特性,导致BinaryFormatter无法直接序列化该类型。你自定义Vector3Ser的思路是正确的,只需确保数据链路全程使用可序列化类型,或手动处理Vector3的序列化逻辑即可解决异常。
解决方案1:替换为自定义可序列化Vector3类
- 完善你的
Vector3Ser类,确保标记序列化特性并提供双向转换方法:
[Serializable] public class Vector3Ser { public float x; public float y; public float z; // 从Unity Vector3转换为可序列化类 public Vector3Ser(Vector3 vec) { x = vec.x; y = vec.y; z = vec.z; } // 转换回Unity Vector3 public Vector3 ToUnityVector3() { return new Vector3(x, y, z); } }
- 修改
PlanetData类,将所有Vector3字段替换为Vector3Ser:
[Serializable] public class PlanetData { public Vector3Ser planetPosition; public Vector3Ser planetRotation; // 其他行星属性(如半径、噪声参数等) // 从行星实例构建序列化数据对象 public PlanetData(Planet planet) { planetPosition = new Vector3Ser(planet.transform.position); planetRotation = new Vector3Ser(planet.transform.eulerAngles); // 赋值其他属性 } // 将序列化数据还原到行星实例 public void LoadToPlanet(Planet planet) { planet.transform.position = planetPosition.ToUnityVector3(); planet.transform.eulerAngles = planetRotation.ToUnityVector3(); // 还原其他属性 } }
- 保持原有保存/加载逻辑,直接序列化
PlanetData列表即可:
public static class SaveSystem { public static void SaveGalaxy(List<PlanetData> galaxyData, string savePath) { BinaryFormatter formatter = new BinaryFormatter(); using (FileStream stream = File.Open(savePath, FileMode.Create)) { formatter.Serialize(stream, galaxyData); } } public static List<PlanetData> LoadGalaxy(string savePath) { if (!File.Exists(savePath)) return null; BinaryFormatter formatter = new BinaryFormatter(); using (FileStream stream = File.Open(savePath, FileMode.Open)) { return formatter.Deserialize(stream) as List<PlanetData>; } } }
解决方案2:实现ISerializable手动处理Vector3序列化
如果不想替换原有Vector3字段,可以让PlanetData实现ISerializable接口,手动控制序列化过程:
[Serializable] public class PlanetData : ISerializable { public Vector3 position; // 其他字段 // 空构造函数(反序列化必须) public PlanetData() { } // 反序列化构造函数 protected PlanetData(SerializationInfo info, StreamingContext context) { position = new Vector3( info.GetSingle("posX"), info.GetSingle("posY"), info.GetSingle("posZ") ); // 读取其他字段 } // 序列化逻辑 public void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("posX", position.x); info.AddValue("posY", position.y); info.AddValue("posZ", position.z); // 写入其他字段 } }
额外注意事项
- 确保
PlanetData及其所有嵌套类都标记了[Serializable](实现ISerializable的类除外) - 不要在序列化类中直接引用Unity组件(如
Transform、Mesh),需提取组件的基础数据(位置、旋转、参数等)进行保存 BinaryFormatter存在安全风险,若面向发布版本,后续可考虑改用JsonUtility或第三方序列化库替代
内容的提问来源于stack exchange,提问作者Crafting Nerf
相关产品推荐
相关产品推荐

