[Serializable]
public class Foo {
public String bar = "Wat";
}
public class Test: MonoBehaviour {
public Foo foo = null;
void Update() {
Debug.Log(foo.bar); // logs Wat
}
} [Serializable]
public class Foo {
public String bar = "Wat";
}
public class Test: MonoBehaviour {
public Foo foo = null;
void Update() {
Debug.Log(foo.bar); // logs Wat
}
}"Inline serialization can’t represent null, instead, it replaces null with an inline object that has unassigned fields."[0]
The key thing here is the [Serializable] attribute above the class. [Serializable] is an attribute provided by the Unity Engine.
It's used to convert in-memory data structures / objects into a format that can be stored and loaded easily. You could use it to build a save system for your game, but more generally it's used for working on your project in the Unity Editor and then savings those to .scene, .prefab, .asset files and so on. Serializable objects and their fields (public fields are serialized by default) are editable in Unity Editor's Inspector tab, which is great for quickly iterating and working with designers who don't want to open a code editor or Excel in order to modify game object values and scenes.
But Serializable has some "wat" moments and one of them is that it does not support null objects.
MonoBehaviour is a Serializable type provided by UnityEngine. You generally make Game Objects by composing together different MonoBehaviours. Because the "Test" Monobehaviour has a public field"Foo foo", it is serialized by default. But it cannot be null. If it is assigned to null, Unity replaces it with an instance that has default field values.
The correct way to handle this (though not very obvious unless you're deep into Unity) is to use the [SerializableReference] attribute instead. Or even better, follow extrememacaroni's recommendation to use Odin's serializer replacement. It's Apache license and basically a drop-in replacement with some additional features.
No non-standard C# involved here, just the runtime reflection allowed by attributes.
[0] https://docs.unity3d.com/Manual/script-Serialization.html
Sure, you could change the declaration of 'bar' to include 'static', and change the access of 'bar' from 'foo.bar' to 'Foo.bar', but... that's not what the code says.
Doesn't Go do this too?