如何在Unity中序列化和保存GameObject

我有一个游戏,玩家拿起一个武器,然后将其作为GameObject变量放置到我的玩家名为“MainHandWeapon”,我试图通过场景更改保存该武器,所以我试图保存它。 我如何处理这个如下:

public class Player_Manager : Character, Can_Take_Damage { // The weapon the player has. public GameObject MainHandWeapon; public void Save() { // Create the Binary Formatter. BinaryFormatter bf = new BinaryFormatter(); // Stream the file with a File Stream. (Note that File.Create() 'Creates' or 'Overwrites' a file.) FileStream file = File.Create(Application.persistentDataPath + "/PlayerData.dat"); // Create a new Player_Data. Player_Data data = new Player_Data (); // Save the data. data.weapon = MainHandWeapon; data.baseDamage = BaseDamage; data.baseHealth = BaseHealth; data.currentHealth = CurrentHealth; data.baseMana = BaseMana; data.currentMana = CurrentMana; data.baseMoveSpeed = BaseMoveSpeed; // Serialize the file so the contents cannot be manipulated. bf.Serialize(file, data); // Close the file to prevent any corruptions file.Close(); } } [Serializable] class Player_Data { [SerializeField] private GameObject _weapon; public GameObject weapon{ get { return _weapon; } set { _weapon = value; } } public float baseDamage; public float baseHealth; public float currentHealth; public float baseMana; public float currentMana; public float baseMoveSpeed; } 

但是,我不断通过此设置获得此错误:

 SerializationException: Type UnityEngine.GameObject is not marked as Serializable. 

我究竟做错了什么?

经过几个小时的实验,我得出结论Unity 不能BinaryFormatter序列化GameObject 。 Unity声称可以在他们的API文档中使用,但事实并非如此

如果你想删除错误而不删除_weapon GameObject,你应该替换…

 [SerializeField] private GameObject _weapon; 

 [NonSerialized] private GameObject _weapon; 

这将使其余代码运行而不抛出exception,但您无法反序列化_weapon 。 您可以反序列化其他字段。

要么

您可以将GameObject序列化为xml 。 这可以毫无问题地序列化GameObject。 它以人类可读的格式保存数据。 如果您关心安全性或不希望玩家在自己的设备上修改分数,您可以加密 ,将其转换为二进制或Base-64格式,然后再将其保存到磁盘。

 using UnityEngine; using System.Collections; using System.Runtime.Serialization.Formatters.Binary; using System.IO; using System; using System.Runtime.Serialization; using System.Xml.Linq; using System.Text; public class Player_Manager : MonoBehaviour { // The weapon the player has. public GameObject MainHandWeapon; void Start() { Save(); } public void Save() { float test = 50; Debug.Log(Application.persistentDataPath); // Stream the file with a File Stream. (Note that File.Create() 'Creates' or 'Overwrites' a file.) FileStream file = File.Create(Application.persistentDataPath + "/PlayerData.dat"); // Create a new Player_Data. Player_Data data = new Player_Data(); //Save the data. data.weapon = MainHandWeapon; data.baseDamage = test; data.baseHealth = test; data.currentHealth = test; data.baseMana = test; data.currentMana = test; data.baseMoveSpeed = test; //Serialize to xml DataContractSerializer bf = new DataContractSerializer(data.GetType()); MemoryStream streamer = new MemoryStream(); //Serialize the file bf.WriteObject(streamer, data); streamer.Seek(0, SeekOrigin.Begin); //Save to disk file.Write(streamer.GetBuffer(), 0, streamer.GetBuffer().Length); // Close the file to prevent any corruptions file.Close(); string result = XElement.Parse(Encoding.ASCII.GetString(streamer.GetBuffer()).Replace("\0", "")).ToString(); Debug.Log("Serialized Result: " + result); } } [DataContract] class Player_Data { [DataMember] private GameObject _weapon; public GameObject weapon { get { return _weapon; } set { _weapon = value; } } [DataMember] public float baseDamage; [DataMember] public float baseHealth; [DataMember] public float currentHealth; [DataMember] public float baseMana; [DataMember] public float currentMana; [DataMember] public float baseMoveSpeed; } 

Unity不会让你这样做,因为Gameobject包含附加到它的所有脚本。 例如网格渲染器,碰撞器等。

如果你想序列化Tranform,你可以通过创建一个新的Vector3位置,Vector3比例,Vector4四元数并将其序列化,然后在反序列化时将这些数据提供给一个新的Transform(例如)来解决这个问题。

但是,尝试序列化与网格渲染器关联的实际网格数据将certificate是非常复杂的任务。 更好的方法可能只是序列化一个int或代表网格ID的东西,然后在加载时将其转换为正确的引用。

理想情况下,你应该有一个持有武器数据的对象(攻击,持久性等等)并序列化这个对象,它使你的保存游戏更小,并且更多OOP,因为你可以inheritance该类。