I have attached a script to a Unity game object. The script contains various public properties, including some of my own classes. Like in the following simplified code, where the TestMonoBehaviorClass
is attached to a game object and the TestClass
' TestString
is shown in the inspector.
public class TestMonoBehaviorClass : MonoBehaviour
{
public TestClass Test;
}
[System.Serializable]
public class TestClass
{
public string TestString;
public TestClass ()
{
Debug.Log ("TestClass creator called.");
this.TestString = "Reset String";
}
}
I would expect that the constructor of the TestClass
(Edit: NOT the one derived from MonoBehavior) is called once, when I attach the script to the game object. But it is called four times if I run the program in the Unity editor and then stop the program. Seven times if I have the script attached to two game objects. At least I see the output of the Debug.Log in the console that many times.
Still, if I change the content of the TestString
property in the editor, the content I enter manually is NOT overwritten!
Why is the constructor called that often? When is it called in Unity's execution order (Unity's execution order of event functions)? Can I kind of ignore the call, or do I have to add special handling into my constructor? So far I didn't see any actual problem or side-effect.
Edit: It seems that only constructors without parameters are called. If I only have constructors with parameters, then none is called.
[System.Serializable]
is why the constructor is being called multiple times. Just ignore it unless there is a bug that results because of that, then ask question about that specific bug for a work-around solution. If you remove [System.Serializable]
, Unity won't serialize the TestClass
class and the constructor will be called once instead of multiple times.
Edit: It seems that only constructors without parameters are called. If I only have constructors with parameters, then none is called.
With [System.Serializable]
, Unity serialization will call the default constructor multiple times during serialization and desalination because it needs to recreate the Object when it is de-serialized. The constructor function is used to do this. See this post for other similar multiple constructor call issue in Unity.
Edit:
If you want to do stuff before or after the serialization is done, you can implement ISerializationCallbackReceiver
interface and use the OnBeforeSerialize()
or OnAfterDeserialize()
function to do this respectively.
For example:
[System.Serializable]
public class TestClass : ISerializationCallbackReceiver
{
public string TestString;
public TestClass()
{
Thread thread = Thread.CurrentThread;
Debug.Log("TestClass creator called: " + thread.ManagedThreadId);
this.TestString = "Reset String";
}
public void OnAfterDeserialize()
{
Thread thread = Thread.CurrentThread;
Debug.LogWarning("OnAfterDeserialize Thread ID: " + thread.ManagedThreadId);
}
public void OnBeforeSerialize()
{
Thread thread = Thread.CurrentThread;
Debug.LogWarning("OnBeforeSerialize Thread ID: " + thread.ManagedThreadId);
}
}