Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by esitoinatteso · Jun 21, 2015 at 07:58 PM · gameobjectvector3serializationcustomhow

" Binary Save" Stuff - Workaround for Vector3 Serialization

Hi there! I'm editing my original question because I was just looking at the tip of the iceberg and thus formulated a too much open/broad/generic question two days ago.

I'm using procedural generation to build the scenes/levels in which my buggy game takes place. It went all good until I decided that'd have been awesome to force the machine to remember those scenes.

Now I'm fighting against the limits of the engine because it seems that, even if Vector 3 should now be a serializable class, many classes I'd like to save into a binary file are not truly serialisable.

It seems that I've managed to get to the point where Unity doesn't crash and executes everything, but the binary files I export are messed up because an error keeps showing up: SerializationException: Type UnityEngine.Vector3 is not marked as Serializable.

Here's what I need:

  1. To Serialize a custom class, MatrixMaster, which is a class that handles all the things procedurally generated in the scene, from the props ( Game Objects) to the grid ( custom class) used by agents to move around

  2. To Deserialize that class

  3. To do it with the type of Serialization I'm most " proficient" with, which is the one with BinaryFormatter

This is, so far, the chunks of code about my custom class I've got:

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
 using System;
 using System.Reflection;
 using System.IO;
 using System.Runtime.Serialization.Formatters.Binary;
 using System.Runtime.Serialization.Formatters;
 using System.Runtime.Serialization;
 
 //using System.Diagnostics;
 
 [Serializable]
 public class MatrixMaster : ScriptableObject, ISerializable {
 
     #region Fields
 
    //A bunch of fields, custom class ones are Serializable
    //GameObjects are comprised
 
     #endregion
 
     #region Properties
 
     //A bunch of properties...
 
     #endregion
 
     // Implement this method to serialize data. The method is called on serialization. 
     public void GetObjectData (SerializationInfo info, StreamingContext context)
     {
         info.AddValue("ScriptableType", this.GetType().AssemblyQualifiedName, typeof(string));
         foreach(FieldInfo field in this.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance))
         {
             info.AddValue(field.Name, field.GetValue(this), field.FieldType);
         }
     }
     
     public void SerializeThisToBinary (){
         
         // To serialize the MatrixMaster and its values, we must first open a stream for writing
         FileStream fs = new FileStream(Application.persistentDataPath + "/matrix_" + this.associatedLevel.ToString() + ".dat", FileMode.Create);
         
         // Construct a BinaryFormatter and use it to serialize the data to the stream.
         BinaryFormatter formatter = new BinaryFormatter();
         try 
         {
             formatter.Serialize(fs, this);
         }
         catch (SerializationException e) 
         {
             Console.WriteLine("Failed to serialize. Reason: " + e.Message);
             throw;
         }
         finally 
         {
             fs.Close();
         }
     }
     
     /// <summary>
     /// Deserializes a matrix saved into a binary file to an instance of that class.
     /// </summary>
     /// <returns>Returns a matrix with the values cached inside the binary file.</returns>
     /// <param name="matrixScene">The number of the scene with which the matrix to load was saved.</param>
     /// <param name="matrix">The instance of the matrix to write into.</param>
     public MatrixMaster DeserializeTo (int matrixScene, out MatrixMaster matrix){
 
         //This is written poorly by me, or a more competent approach see this: https://msdn.microsoft.com/it-it/library/b85344hz(v=vs.110).aspx
         //I like the Try Catch Finally thing
 
         //Construct a BinaryFormatter and use it to deserialize the data to the stream
         BinaryFormatter formatter = new BinaryFormatter();
 
         //Open the file containing the data we want to deserialize
         FileStream file = File.Open(Application.persistentDataPath + "/matrix_" + matrixScene.ToString() + ".dat", FileMode.Open);
 
         //Declare the instance reference
         matrix = ScriptableObject.CreateInstance<MatrixMaster>();
 
         // Deserialize the MatrixMaster from the file and assign the reference to the local variable
         matrix = (MatrixMaster) formatter.Deserialize(file);
 
         //Close the stream
         file.Close();
 
         //Return
         return matrix;
     }
 }
 

I've referenced a lot of stuff to get to this point ( I'm quoting all links because I'd like question to be helpful to others too and this sets everybody on the same page):

  • ISerializable Interface

  • Wrapping Up ISerializables

  • Deserialize Method

  • SerializationInfo

  • Implement ISerializable correctly

  • Custom Serialization

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image esitoinatteso · Jun 22, 2015 at 10:25 AM 0
Share

First bump

3 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Cherno · Jun 23, 2015 at 04:05 PM

ISerializationSurrogates are what you want. Even though Unity-internal, Vector3 is serializable, this has nothing to do with Serializable as NET understands it; these are two completely different things unfortunately using the same term. That being said, implementing ISS is pretty easy. I posted the required code in the comments below my answer in this thread. As an added note, You will most likely encounter further serialization problems when trying to serialize GameObject variables (and other Types specific to Unity, like Transform, Texture2D, ...). You can create a custom attribute to skip this field, but then you will again encounter the error if you serialize a variable of type ClassXY which itself has a variable of type GameObject. For these cases, I recommend creating ISS for each Type that gives an error you can't avoid, and just pass no values inside the ISS, like this:

 using System.Runtime.Serialization;
 using UnityEngine;
 
 sealed class GameObjectSerializationSurrogate : ISerializationSurrogate {
     
     // Method called to serialize a GameObject object
     public void GetObjectData(System.Object obj,
                               SerializationInfo info, StreamingContext context) {
         
         GameObject go = (GameObject) obj;
         //Debug.Log(go);
     }
     
     // Method called to deserialize a GameObject object
     public System.Object SetObjectData(System.Object obj,
                                        SerializationInfo info, StreamingContext context,
                                        ISurrogateSelector selector) {
         
         GameObject go = (GameObject) obj;
         
         //obj = go;
         return obj;   // Formatters ignore this return value //Seems to have been fixed!
     }
 }


 


Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image esitoinatteso · Jun 23, 2015 at 04:21 PM 0
Share

Awesome pal! You just gave me something to chew on! I'll study and try what you just kindly suggested and linked in the next days :D

Thanks a lot!

P.S.: As soon as I manage to understand and implement it, I'll mark it as an answer ;)

avatar image esitoinatteso · Jun 25, 2015 at 04:45 PM 0
Share

Hi Cherno! Thanks again for your suggestion! I unfortunately have the need to bother you again, if you don't $$anonymous$$d, because I still have a problem:

it seems the GameObjects I'm deserialising return null, as if everything about them got deleted.

I followed the process when caching them as GameObjects and the Surrogate kicks in properly. Its method GetObjectData() works and shows expected values for GameObjects.

When deserialising though, their method kicks in with obj always null.

Am I doing something wrong with the call to deserialise? Here it is:

     // The special constructor is used to deserialize values. 
     public CustomClass(SerializationInfo info, Strea$$anonymous$$gContext context)
     {
         // Reset the property value using the GetValue method.
         objectsInSceneByName = (List<string>) info.GetValue("names", typeof(List<string>));
         objectsInScene = (List<GameObject>) info.GetValue("objects", typeof(List<GameObject>));
     }

I'm asking for deserialisation from another class, with BinaryFormatter, Surrogate Selector and FileStream all set up.

Do I have to cache GameObjectSerializationSurrogates ins$$anonymous$$d of Game Objects? Or maybe I have to modify their method to cache all the values stored inside the GameObject go? I've tried but with no success!

avatar image Cherno · Jun 25, 2015 at 05:24 PM 1
Share

Of course they return null, since no value pertaining to the variable in question was serialized. This was just so you can actually serialize classes which have GameObject fields. To actually serialize and deserialize a whole gameobject.. well, let's just say that it's not pretty. I managed to do it but it's far too much work to explain it all in here, sorry. $$anonymous$$aybe one day I will write a tutorial on this. It's all about finding workarounds: How to serialize a Transform component? Well, you already know how to serialize V3s, so now you just need a class representing a GameObject that holds the Vector3s of a Transform component, and so on. When deserializing, you use these values to assign the Transform's Vector3s again. Generally, you need to serialize the prefab name and/or path of each gameobject so a prefab of it can be created upon deserialization. This is all very complicated so excuse me if what I wrote doesn'T make much sense. All I can say is that I spend weeks of trial and error until I got a working solution.

avatar image esitoinatteso · Jun 25, 2015 at 05:42 PM 0
Share

Cool, I'd be definitely interested in a tutorial that explains those kind of things!

By the way, no need to excuse yourself! I can imagine how much effort such explanations would require and I understand that this is not the place for such a broad and extended essay... plus you've already done a lot!

I've resolved caching only those values I really need, that means 3 lists of floats and a list of strings. By saving x,y,z coordinates and the name of the object, I can reload it from Resources and instantiate it to the desired position.

" To actually serialize and deserialize a whole gameobject.. well, let's just say that it's not pretty." Thanks a lot for pointing this out, I couldn't imagine!

So, again, thank you really much for the efforts and the kind replies! I think we can mark this question as solved!

Good luck with your coding trials!

avatar image Cherno · Jun 25, 2015 at 05:45 PM 0
Share

Glad to be of help. Questions like these inch me further towards writing the tutorial; If anything, It will allow me to just link to it ins$$anonymous$$d of writing a paragraph of explaination ;) I bookmarked this threaed and will come back to it should I ever get this tutorial done (or started!).

Show more comments
avatar image
0

Answer by MidnightStudiosInc · Jul 01, 2015 at 03:30 PM

GameObject Serializer Pro includes many of the commonly needed surrogates out-of-the-box (Transform, Texture, Mesh, Vector3, etc... full list is here) that way you won't need to write them. It can serialize and deserialize entire GameObjects and preserve references where subclasses of UnityEngine.Object are used.

It's also built on top of protobuf-net, making it forward-compatible with future versions of .Net/Mono (unlike BinaryFormatter) and much more efficient than XMLSerializer.

If you need more types that are not listed in the supported types list I would be glad to add them.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by herbou · Jun 24, 2020 at 11:50 AM

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

PACKAGE: https://github.com/herbou/Unity_GenericBinarySerializer

TUTORIAL: https://youtu.be/PbPCW8vK3RQ

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

25 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Can a GameObject be serialized? 1 Answer

How to align the bottom of a GameObject with the ground? 1 Answer

Accessing game object based on position 2 Answers

2D Get Object Height to stack up on the screen 1 Answer

How to shoot a bullet on a moving object,How to shoot a bullet from an object moving in the direction of motion 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges