c# - tag - Cómo serializar y guardar un GameObject en Unity
obtener la posicion de un objeto unity (3)
Tengo un juego donde el jugador toma un arma y luego se coloca como la variable GameObject para mi jugador llamada "MainHandWeapon" y estoy tratando de guardar esa arma a través de cambios de escena, así que estoy tratando de guardarla. La forma en que manejo esto es la siguiente:
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;
}
Pero sigo recibiendo este error al tener esta configuración:
SerializationException: Type UnityEngine.GameObject is not marked as Serializable.
¿Qué estoy haciendo mal exactamente?
Después de horas de experimento, llegué a la conclusión de que Unity
no puede
serializar
GameObject
con
BinaryFormatter
.
Unity afirma que es posible en su documentación API pero no lo es.
Si desea eliminar el error sin eliminar _weapon GameObject, debe reemplazar ...
[SerializeField]
private GameObject _weapon;
con
[NonSerialized]
private GameObject _weapon;
Esto permitirá que el resto del código se ejecute sin
_weapon
excepciones, pero no
puede
deserializar
_weapon
GameObject.
Puede
deserializar
otros campos.
O
Puede serializar GameObject como xml . Esto puede serializar GameObject sin ningún problema. Guarda los datos en formato legible para humanos. Si le importa la seguridad o no quiere que los jugadores modifiquen las puntuaciones en sus propios dispositivos, puede encrypt , convertirlos a formato binary o encrypt antes de guardarlo en el disco.
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;
}
Idealmente, debe tener un objeto que contenga los datos del arma (ataque, durabilidad, etc.) y serializar este objeto, hace que sus partidas guardadas sean mucho más pequeñas y tiene más OOP, como puede heredar de esa clase.
Unity no te permitirá hacerlo porque un Gameobject se compone de todos los scripts adjuntos. Por ejemplo, reproductores de malla, colisionadores, etc.
Si desea decir serializar la Transformación, puede evitar esto haciendo una nueva posición Vector3, escala Vector3, Quaternion Vector4 y serializando eso en su lugar y luego, en la deserialización, alimente estos datos en una nueva Transformación (por ejemplo).
Pero intentar serializar los datos de malla reales que están asociados con el renderizador de malla sería una tarea bastante compleja. Mejor probablemente, simplemente serializando un int o algo que represente una ID de malla y luego transmutando esto a la referencia correcta en la carga.