How can i serialize a Quaternion?

I’m trying to Serialize a Class I made that has a Quaternion in it, but i get this error on run time:

“SerializationException: Type UnityEngine.Quaternion is not marked as Serializable.”

After reading this page I understood that Quaternions are only serialized by the Unity’s own serializer and not by the one from the System namespace.

So how can i do this?

Would it be good enough to serialize the Quaternion’s fields x, y, z, w? or in other words can we save a quaternion as 4 simple values? Is there a better option that anyone knows of?

Thank you all, majorly ‘whydoidoit’ and ‘Dracorat’ for the replys, meanwhile I solved my problem, using the System Serializer (the hard and long path). So this is how i did it:

using UnityEngine;
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
 

//my Node class to be serialized
[Serializable]
public class MyClass : ISerializable
{
[NonSerializedAttribute] //dont forget to add this
public Quaternion DIR;

[NonSerializedAttribute] //im serious
public List<Transform> objParts;

public MyClass(Transform[] components, Quaternion vector)
{
    DIR = new Quaternion();
    DIR = vector;
    objParts=new List<Transform>();

    foreach(Transform t in components)
    {
        Transform temp = new GameObject().transform;
        temp.rotation = t.rotation;
        temp.position = t.position;
        objParts.Add(temp);
    }

}

//Serialization function (this one gived an headhache x.x).
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
    info.AddValue("DIRx",DIR.x);
    info.AddValue("DIRy",DIR.y);
    info.AddValue("DIRz",DIR.z);
    info.AddValue("DIRw",DIR.w);
    info.AddValue("ObjectCount",objParts.Count);
    for(int i=0; i<objParts.Count; i++)
    {
    	info.AddValue("Part"+i+"rotation"+"x",objParts*.rotation.x);*

_ info.AddValue(“Part”+i+“rotation”+“y”,objParts*.rotation.y);_
_ info.AddValue(“Part”+i+“rotation”+“z”,objParts.rotation.z);
info.AddValue(“Part”+i+“rotation”+“w”,objParts.rotation.w);*_

_ info.AddValue(“Part”+i+“position”+“x”,objParts*.position.x);
info.AddValue(“Part”+i+“position”+“y”,objParts.position.y);
info.AddValue(“Part”+i+“position”+“z”,objParts.position.z);
}
}*_

//Deserialization constructor (holy cow).
public MyClass(SerializationInfo info, StreamingContext ctxt)
{
//Get the values from info and assign them to the appropriate properties
DIR.x = (float)info.GetValue(“DIRx”, typeof(float));
DIR.y = (float)info.GetValue(“DIRy”, typeof(float));
DIR.z = (float)info.GetValue(“DIRz”, typeof(float));
DIR.w = (float)info.GetValue(“DIRw”, typeof(float));

int Nparts = (int)info.GetValue(“Nparts”, typeof(int));
objParts = new List();
for(int i=0; i<Nparts; i++)
{
Transform temp = new GameObject().transform;
Vector4 tempv4 = new Vector4();
Vector3 tempv3 = new Vector3();

tempv4.x = (float)info.GetValue(“Part”+i+“rotation”+“x”, typeof(float));
tempv4.y = (float)info.GetValue(“Part”+i+“rotation”+“y”, typeof(float));
tempv4.z = (float)info.GetValue(“Part”+i+“rotation”+“z”, typeof(float));
tempv4.w = (float)info.GetValue(“Part”+i+“rotation”+“w”, typeof(float));

tempv3.x = (float)info.GetValue(“Part”+i+“position”+“x”, typeof(float));
tempv3.y = (float)info.GetValue(“Part”+i+“position”+“y”, typeof(float));
tempv3.z = (float)info.GetValue(“Part”+i+“position”+“z”, typeof(float));

temp.rotation=new Quaternion(tempv4.x,tempv4.y,tempv4.z,tempv4.w);
temp.position=tempv3;

objParts.Add(temp);
}
}

}

Sorry to take so long to reply, I’ve been reading trough stuff about unity serializer, all your suggestions and stuff, and trying to understand all of the info.
And now i have more questions and doubts then when i started.

First of i need to clear things out, I’m not just trying to serialize a quaternion but also lots of other stuff, i just taught that knowing how to serialize a quaternion would be a good start on saving all i need to, this is not exactly for a game, but in my point of view unity is the best place to do it due to several factors.

So the problem is the next, I have an N-ary tree with lots of nodes that i made my own, each node has lot of stuff\information in it, from Quaternions to Transforms. This tree is created and expanded when the program runs, and it runs perfectly, it took me a couple mouths to make it perfect.

But then i came to the problem of when i close my program, the tree vanishes and the next time I run the program I’ll need to generate the tree back from the beginning, meaning, I’ll never get anywhere with this unless I leave the computer always on for days.

So I started serializing stuff, first I had no idea unity had he’s own serializer and as I knew a bit of the System one I started using it, but then I came to the problem in the initial post. So basically if the nodes only had “light” variables it would serialize well and I would have all the code already done, but as I’m trying to save unity variables… well, I’m kinda stuck.

Like i said, after reading and watching some stuff about this, i now am very confused, and i have no idea how to use unity’s serializer in here, or if I’ll need to replace all the serialization stuff I had already done.

And so I don’t know how to exactly ask for help, but I do feel like I really need it to do this :frowning:

So my best thinking is of making a little example of what I have (in a small scale and without any tree) and ask someone who knows how to just modify it\change it\ remake it in order to work.

So here’s the code of an example of what i have (it obviously gives error when trying to serialize the quaternion and transforms):

using UnityEngine;
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;

//My saving function
void saveToFile(MyClass obj)
{
    Stream stream = File.Open("Memory.mem", FileMode.Create);
	
    BinaryFormatter bformatter = new BinaryFormatter();
	            
    bformatter.Serialize(stream, obj);

    stream.Close();
}



//my Node class to be serialized
[Serializable]
public class MyClass : ISerializable
{
    public Quaternion DIR;
    public List<Transform> objParts;

    public MyClass(Transform[] components, Quaternion vector)
    {
        DIR = new Quaternion();
        DIR = vector;
        objParts=new List<Transform>();

        foreach(Transform t in components)
        {
            Transform temp = new GameObject().transform;
            temp.rotation = t.rotation;
            temp.position = t.position;
            objParts.Add(temp);
        }

    }

    //Serialization function.
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("DIR",DIR);
        info.AddValue("objParts",objParts);
    }
	
    //Deserialization constructor.
    public MyClass(SerializationInfo info, StreamingContext ctxt)
    {
        //Get the values from info and assign them to the appropriate properties
        DIR = (Quaternion)info.GetValue("DIR", typeof(Quaternion));
        objParts = (List<Transform>)info.GetValue("objParts", typeof(List<Transform>));
    }

}

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 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.

GameObject Serializer Pro can serialize Vectors and Quaternions directly and simply, with much more. It’s also much more efficient than XmlSerializer and is forward/backward-compatable (unlike BinarySerializer)