Serialize Quaternion or Vector3

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;
}

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:

1

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;

About a year ago, when I barely knew how to code, I copied @Cherno 's code for the SerializableVector3 and SerializableQuaternion structs. Since then I’ve improved the code, and I thought I’d post it here in case it’s helpful to someone else. Here are my changes:

  • removed a ton of useless s
  • improve code formatting so that it’s neater and more readable
  • renamed a bunch of stuff, including the classes themselves; they’re called SVector3 and SQuaternion now, which is much nicer to use
  • added +, -, * and / operators to SerializableVector3
  • added SColor32 class

And here’s the code:

namespace SerializableTypes
{
    /// <summary> Serializable version of UnityEngine.Vector3. </summary>
    [Serializable]
    public struct SVector3
    {
        public float x;
        public float y;
        public float z;

        public SVector3(float x, float y, float z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public override string ToString()
            => $"[x, y, z]";

        public static implicit operator Vector3(SVector3 s)
            => new Vector3(s.x, s.y, s.z);

        public static implicit operator SVector3(Vector3 v)
            => new SVector3(v.x, v.y, v.z);


        public static SVector3 operator +(SVector3 a, SVector3 b) 
            => new SVector3(a.x + b.x, a.y + b.y, a.z + b.z);

        public static SVector3 operator -(SVector3 a, SVector3 b)
            => new SVector3(a.x - b.x, a.y - b.y, a.z - b.z);

        public static SVector3 operator -(SVector3 a)
            => new SVector3(-a.x, -a.y, -a.z);

        public static SVector3 operator *(SVector3 a, float m)
            => new SVector3(a.x * m, a.y * m, a.z * m);

        public static SVector3 operator *(float m, SVector3 a)
            => new SVector3(a.x * m, a.y * m, a.z * m);

        public static SVector3 operator /(SVector3 a, float d)
            => new SVector3(a.x / d, a.y / d, a.z / d);
    }

    /// <summary> Serializable version of UnityEngine.Quaternion. </summary>
    [Serializable]
    public struct SQuaternion
    {
        public float x;
        public float y;
        public float z;
        public float w;

        public SQuaternion(float x, float y, float z, float w)
        {
            this.x = x;
            this.y = y;
            this.z = z;
            this.w = w;
        }

        public override string ToString()
            => $"[{x}, {y}, {z}, {w}]";

        public static implicit operator Quaternion(SQuaternion s)
            => new Quaternion(s.x, s.y, s.z, s.w);

        public static implicit operator SQuaternion(Quaternion q)
            => new SQuaternion(q.x, q.y, q.z, q.w);
    }

    /// <summary> Serializable version of UnityEngine.Color32 without transparency. </summary>
    [Serializable]
    public struct SColor32
    {
        public byte r;
        public byte g;
        public byte b;

        public SColor32(byte r, byte g, byte b)
        {
            this.r = r;
            this.g = g;
            this.b = b;
        }

        public SColor32(Color32 c)
        {
            r = c.r;
            g = c.g;
            b = c.b;
        }

        public override string ToString()
            => $"[{r}, {g}, {b}]";

        public static implicit operator Color32(SColor32 rValue)
            => new Color32(rValue.r, rValue.g, rValue.b, a: byte.MaxValue);

        public static implicit operator SColor32(Color32 rValue)
            => new SColor32(rValue.r, rValue.g, rValue.b);
    }
}

If you want to make your own serializable versions of Unity structs - i.e. Color, Vector2, Vector3Int, ect - the Unity C# Reference is a great resource. You can find the full Unity source code for the struct you need.

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 SurrogateSelector Class (System.Runtime.Serialization) | Microsoft Learn

But if you want to avoid all the trouble and save time, then check out Cross Platform Easy Save fast and efficient plugin designed to handle serialization of c# class object as well Unity Objects like GameObject, Transform, Textures etc.

You can have a look at complete Scene Serialization over here

Iam using the epic free GitHub - jacobdufault/fullserializer: A robust JSON serialization framework that just works with support for all major Unity export platforms.

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.

If you’re using Json.net there are some custom converters available for free in the asset store at Unity Asset Store - The Best Assets for Game Making

@JimmyCushnie

Hey! Thanks for this update. I am a fairly new coder and I am struggling with the same problem now. Would you be able to explain a bit how I would go on about using this?

Would I replace all my Vector3 variables in my project with a SVector 3, and that’s it? (by all I mean all the ones I am interested in saving/serializing)

Or do I need to call any of those methods inside the struct?

Can you elaborate on all those static implicit operators ?

A Generic BinarySerializer tool , Easy to use. Supports : Vectors, Colors, and Quaternions too.

PACKAGE: GitHub - herbou/Unity_GenericBinarySerializer

TUTORIAL: Unity 💾 Save your game data as binary, 2 lines of code📄 - YouTube

Not sure about everyone else, but I found that Vector2/3 are actually Serialized when inside another class (My 2 cents). as example:

    [Serializable]
    public class serializableVector3 {
        public Vector3 position;
    }

private serializableVector3  myTest;

Will serialize the vector3 inside the class. I use this method to read/write.

idk precisely from which version of Unity this is supported but I am using JSONUtility with Unity 2019.2.17f1 and I can save vector3 and quaternions without any need of whatever the other guys are using like custom Vector classes and surrogates. Check out this very straightforward tutorial