You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用BinaryFormatter保存行星数据时触发Vector3序列化异常

解决Unity BinaryFormatter序列化Vector3的SerializationException问题

核心问题原因

Unity内置的UnityEngine.Vector3未标记符合.NET要求的[Serializable]特性,导致BinaryFormatter无法直接序列化该类型。你自定义Vector3Ser的思路是正确的,只需确保数据链路全程使用可序列化类型,或手动处理Vector3的序列化逻辑即可解决异常。

解决方案1:替换为自定义可序列化Vector3类

  1. 完善你的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);
    }
}
  1. 修改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();
        // 还原其他属性
    }
}
  1. 保持原有保存/加载逻辑,直接序列化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 14:03:24