Categories: All - assets - objects

by Mike Ton 7 years ago

555

Unity3D_Serialization

Unity's serialization system allows developers to store and manage data efficiently within their projects. Assets and objects in Unity can have complex relationships, including inter-object references where UnityEngine.

Unity3D_Serialization

Serialization

Assets, Objects and serialization

1.2. Inter-Object references
(references)

All UnityEngine.Objects can have references to other UnityEngine.Objects

1.1. Inside Assets and Objects
UnityEngine.Objects

While most Object types are built-in, there are two special types

MonoBehaviour

a wrapper that links to a MonoScript

The MonoScript does not contain any actual executable code.

MonoScript is an internal data type that Unity uses to hold a reference to a specific scripting class within a specific assembly and namespace

ScriptableObject

can be natively serialized and deserialized and manipulated in the Inspector window

provides a convenient system for developers to define their own data types

set of serialized data collectively describing a specific instance of a resource

Objects are subclasses of the UnityEngine.Object base class

any type of resource which the Unity Engine uses

such as a mesh, a sprite, an AudioClip or an AnimationClip

Assets

file on disk, stored in the Assets folder of a Unity project

Other Assets need to be processed into native formats, such as FBX files.

Some Assets contain data in formats native to Unity, such as materials.

one-to-many relationship between Assets and Objects

any given Asset file contains one or more Objects

https://unity3d.com/learn/tutorials/temas/best-practices/assets-objects-and-serialization
what are these situations where the serializer behaves differently from what I expect?
No support for null for custom classes

class Test : MonoBehaviour{ public Trouble t; } [Serializable] class Trouble{ public Trouble t1; public Trouble t2; public Trouble t3; }

Custom classes behave like structs

class Animal{ public string name; } class MyScript : MonoBehaviour{ public Animal[] animals; }

If you need to serialize a complex object graph with references, you cannot rely on Unity’s serializer doing that all automagically for you, and have to do some work to get that object graph serialized yourself.

When it’s deserialized, there are now three different objects.

If you populate the animals array with three references to a single Animal object, in the serializationstream you will find 3 objects.

Which fieldtypes can we serialize?
List of a fieldtype we can serialize
Array of a fieldtype we can serialize
Primitive data types (int,float,double,bool,string,etc)
References to objects that derive from UntiyEngine.Object
Custom structs with [Serializable] attribute. (new in Unity4.5)
Custom non abstract classes with [Serializable] attribute.
What does a field of my script need to be in order to be serialized?
The fieldtype needs to be of a type that we can serialize.
Not be

readonly

const

static

Be public

or have [SerializeField] attribute

Unity features are built ontop of the serialization system:
File I/O

Loading

Assetbundles also make use of the serialization system.

Might not seem surprising, but backwards compatible loading is a system that is built on top of serialization as well.

In-editor yaml loading uses the serialization system, as well as the runtime loading of scenes and assets.

Saving

If you open a .unity scene file with a text editor, and have set unity to “force text serialization”, we run the serializer with a yaml backend.

RunTime

Resource.GarbageCollectSharedAssets()

This is what makes textures that were used by scene1, get unloaded when you load scene2.

This is our native garbage collector and is different to the C# garbage collector

The native garbage collector runs the serializer in a mode where we use it to have objects report all references to external UnityEngine.Objects.

It is the thing that we run after you load a scene to figure out which things from the previous scene are no longer referenced, so we can unload them

Instantiation

And then we “deserialize” the data onto the new object.

(If the reference is pointing to something “external” (like a texture) we keep that reference as it is, if it is pointing to something “internal” (like a child gameobject), we patch the reference to the corresponding copy).

We then run the same serialization code again in a different variant, where we use it to report which other UnityEngine.Object’s are being referenced. We then check for all referenced UnityEngine.Object’s if they are part of the data being Instantiated().

When you call Instantiate() on either a prefab, or a gameobject that lives in the scene, or on anything else for that matter (everything that derives from UnityEngine.Object can be serialized), we serialize the object, then create a new object

Editor

Hot reloading of editor code.

When you change an editor script, we serialize all editor windows

and finally deserialize the datastreams of the windows back onto the new windows

recreate the windows

load the new c# code

unload the old c# code

we then destroy all the windows

(they derive from UnityEngine.Object!),

Prefabs

The concept prefab actually only exists at editor time.

A prefab instance is a list of modifications that should be made on the serialized data for this instance.

The prefab modifications get baked into a normal serialization stream when Unity makes a build, and when that gets instantiated, the instantiated gameobjects have no idea they were a prefab when they lived in the editor.

Internally, a prefab is the serialized data stream of one (or more) game objects and components

The serialization system is written in C++, we use it for all our internal object types (Textures, AnimationClip, Camera, etc)

They can contain references to other UnityEngine.Objects and those references get serialized properly.

Serialization happens at the UnityEngine.Object level, each UnityEngine.Object is always serialized as a whole.

Storing data stored in your scripts