It seems like saving your players location and rotation would be pretty common, but I can't seem to find any example of serializing a Quaternion or Vectory3 anywhere.
According to the unity docs here it says the both are serializable but I keep getting the following error "SerializationException: Type UnityEngine.Quaternion is not marked as Serializable." when trying to serialize the following class.
[Serializable]
public class Entity{
public string entityName;
public Quaternion entityRotation;
}
What exactly do you mean by serialize? Do you mean "let Unity serialize the class" or do you mean you tried to serialize the class with .NET's / mono's serialization system?
More context please.
I guess that you try to manually serialize it. In this case, no, it's not compatible with .NET / mono serialization. You have to implement ISerializable and provide a custom serialization method. I'l post an answer ^^
Thanks for the responses. I was hoping I didn't have to manually do this and was just missing something simple in Unity that would automatically serialize these objects.
个解答,截止Cherno · 2015年04月28日 23:46
Here are serializable versions of the Vector3 and Quaternion class, with automatic conversion:
using UnityEngine;
using System;
using System.Collections;
/// <summary>
/// Since unity doesn't flag the Vector3 as serializable, we
/// need to create our own version. This one will automatically convert
/// between Vector3 and SerializableVector3
/// </summary>
[System.Serializable]
public struct SerializableVector3
{
/// <summary>
/// x component
/// </summary>
public float x;
/// <summary>
/// y component
/// </summary>
public float y;
/// <summary>
/// z component
/// </summary>
public float z;
/// <summary>
/// Constructor
/// </summary>
/// <param name="rX"></param>
/// <param name="rY"></param>
/// <param name="rZ"></param>
public SerializableVector3(float rX, float rY, float rZ)
{
x = rX;
y = rY;
z = rZ;
}
/// <summary>
/// Returns a string representation of the object
/// </summary>
/// <returns></returns>
public override string ToString()
{
return String.Format("[{0}, {1}, {2}]", x, y, z);
}
/// <summary>
/// Automatic conversion from SerializableVector3 to Vector3
/// </summary>
/// <param name="rValue"></param>
/// <returns></returns>
public static implicit operator Vector3(SerializableVector3 rValue)
{
return new Vector3(rValue.x, rValue.y, rValue.z);
}
/// <summary>
/// Automatic conversion from Vector3 to SerializableVector3
/// </summary>
/// <param name="rValue"></param>
/// <returns></returns>
public static implicit operator SerializableVector3(Vector3 rValue)
{
return new SerializableVector3(rValue.x, rValue.y, rValue.z);
}
}
Quaternion:
using UnityEngine;
using System;
using System.Collections;
/// <summary>
/// Since unity doesn't flag the Quaternion as serializable, we
/// need to create our own version. This one will automatically convert
/// between Quaternion and SerializableQuaternion
/// </summary>
[System.Serializable]
public struct SerializableQuaternion
{
/// <summary>
/// x component
/// </summary>
public float x;
/// <summary>
/// y component
/// </summary>
public float y;
/// <summary>
/// z component
/// </summary>
public float z;
/// <summary>
/// w component
/// </summary>
public float w;
/// <summary>
/// Constructor
/// </summary>
/// <param name="rX"></param>
/// <param name="rY"></param>
/// <param name="rZ"></param>
/// <param name="rW"></param>
public SerializableQuaternion(float rX, float rY, float rZ, float rW)
{
x = rX;
y = rY;
z = rZ;
w = rW;
}
/// <summary>
/// Returns a string representation of the object
/// </summary>
/// <returns></returns>
public override string ToString()
{
return String.Format("[{0}, {1}, {2}, {3}]", x, y, z, w);
}
/// <summary>
/// Automatic conversion from SerializableQuaternion to Quaternion
/// </summary>
/// <param name="rValue"></param>
/// <returns></returns>
public static implicit operator Quaternion(SerializableQuaternion rValue)
{
return new Quaternion(rValue.x, rValue.y, rValue.z, rValue.w);
}
/// <summary>
/// Automatic conversion from Quaternion to SerializableQuaternion
/// </summary>
/// <param name="rValue"></param>
/// <returns></returns>
public static implicit operator SerializableQuaternion(Quaternion rValue)
{
return new SerializableQuaternion(rValue.x, rValue.y, rValue.z, rValue.w);
}
}
Also check out this guide to Surrogates, very useful:
Here is a ISerializationSurrogate for Vector3:
using System.Runtime.Serialization;
using UnityEngine;
sealed class Vector3SerializationSurrogate : ISerializationSurrogate {
// Method called to serialize a Vector3 object
public void GetObjectData(System.Object obj,
SerializationInfo info, StreamingContext context) {
Vector3 v3 = (Vector3) obj;
info.AddValue("x", v3.x);
info.AddValue("y", v3.y);
info.AddValue("z", v3.z);
Debug.Log(v3);
}
// Method called to deserialize a Vector3 object
public System.Object SetObjectData(System.Object obj,
SerializationInfo info, StreamingContext context,
ISurrogateSelector selector) {
Vector3 v3 = (Vector3) obj;
v3.x = (float)info.GetValue("x", typeof(float));
v3.y = (float)info.GetValue("y", typeof(float));
v3.z = (float)info.GetValue("z", typeof(float));
obj = v3;
return obj; // Formatters ignore this return value //Seems to have been fixed!
}
}
You can include the Surrogate in your formatter like this:
BinaryFormatter bf = new BinaryFormatter();
// 1. Construct a SurrogateSelector object
SurrogateSelector ss = new SurrogateSelector();
Vector3SerializationSurrogate v3ss = new Vector3SerializationSurrogate();
ss.AddSurrogate(typeof(Vector3),
new StreamingContext(StreamingContextStates.All),
v3ss);
// 2. Have the formatter use our surrogate selector
bf.SurrogateSelector = ss;
All of the Unity-specific classes are non-serializable. Check the comments under the OP, where the differences between Unity and .NET serialization are explained.
个解答,截止Voxel-Busters · 2015年08月07日 12:03
You won't be able to serialise Vectors, Colors and Quaternions directly as they are not Serializable classes. But c# allows you to implement serialization extensions classes using ISerializationSurrogate. Check this link for more info https://msdn.microsoft.com/en-us/library/system.runtime.serialization.surrogateselector%28v=vs.110%29.aspx
But if you want to avoid all the trouble and save time, then check out Runtime Serialization for Unity fast and efficient plugin designed to handle serialization of c# class object as well Unity Objects like GameObject, Transform, Textures etc.
个解答,截止aeroson · 2016年01月04日 11:34
Iam using the epic free https://github.com/jacobdufault/fullserializer
个解答,截止Bunny83 · 2015年04月28日 20:09
In case you talk about .NET / mono serialization you have to implement the ISerializable interface like this:
using System.Runtime.Serialization;
public class Entity : ISerializable
{
public string entityName;
public Quaternion entityRotation;
public Entity(SerializationInfo info, StreamingContext context)
{
entityName = info.GetString("name");
entityRotation.x = info.GetSingle("RotationX");
entityRotation.y = info.GetSingle("RotationY");
entityRotation.z = info.GetSingle("RotationZ");
entityRotation.w = info.GetSingle("RotationW");
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("name", entityName);
info.AddValue("RotationX", entityRotation.x);
info.AddValue("RotationY", entityRotation.y);
info.AddValue("RotationZ", entityRotation.z);
info.AddValue("RotationW", entityRotation.w);
}
}
GameObject Serializer Pro serializes Vector3, Quaternion, and much more. Unlike BinaryFormatter it is forward-compatable with future versions of .Net/Mono. It's also much more efficient than XmlSerializer.
联系客服