Private constructor called at playmode start, empty callstack

It often happens to me that a constructor of a class is called even if nobody is calling it. Callstack begins at this call, so i assume it’s called externally (outside CLR) by the unity engine. I can see no pattern here, and some are called many hundred times. Is there something the engine does i should know about? Is there anyone who noticed similar behaviour?

PS: Please don’t lecture me about “unity discouraging from using constructors” as this is only related to UnityEngine.Object derived classes, which is not the case (and i don’t like how the no constructor policy is mistified by many)

Have you any example code? I assume, from your description, that you talk about one of your own classes that is not derived from UnityEngine.Object (So it’s not a MonoBehaviour or ScriptableObject or something like that).

If you never create an instance of that class the constructor won’t ever be executed. The only situation which i can imagine you might have here is, when you mark a custom class with the Serializable attribute and use it as a serialized member of a MonoBehaviour or ScriptableObject class.

Example:

[System.Serializable]
public class MyDataClass
{
    public int someField = 0;
    private MyDataClass()
    {
        Debug.Log("MyDataClass instance created");
    }
}

public class MyComponent : MonoBehaviour
{
    public MyDataClass data1;
    
    [SerializaField]
    private MyDataClass data2;
    public MyDataClass[] data3;
}

Now if you attach that component to a gameObject in the editor, the editor will create an instance of MyDataClass at least for the data1 and data2 fields. If you change the size of the data3 array, the editor will also create an instance for each array member. Those instances are now serialized with the component when the scene / prefab is saved in the project.

At runtime when the scene / prefab get loaded those instance are of course recreated and deserialized afterwards. The same happens when you instantiate / clone an object with that component attached. Instantiate actually serializes the whole object and then recreates the object from the serialized data to get the clone. During that process the new clone will receive new instances of our MyDataClass.

So to sum up: “Serializable custom classes” are treated like structs by Unity’s serialization system. “Normal”, non-serializable custom classes behave just like in normal plain C#. You only will have an instance if you create one somewhere.

ps: That’s another reason why using reflection to create an instance of a class is never a good idea, since you can’t track who’s actually creating an instance.

@Pangamini did you figure this out? Im pretty sure im getting the same thing. just like for you, putting a breakpoint in the constructor reveals no callstack.

see below for code - post this into a monobehaviour WhyConstruct.cs and put it on a gameobject. then any time you update the code and unity builds it, it will call the constructor. also each time you enter play mode the same happens. i’m guessing this is some fancy reflection stuff that happens when unity copy/refreshes the state of the scene, like when you update hte code or enter playmode. notice that i even made the constructor private, and _somePropertyValue should always have the value null!

i found two hacks to stop it happening. one was to give the constructor a dummy argument (e.g. an int), so that there was no constructor with 0 args. the second was to mark _somePropertyValue as NonSerialized attribute. both are ugly in the context of my project :(. if anyone has other suggestions please let me know.

using UnityEngine;

public class WhyConstruct : MonoBehaviour
{
    [System.Serializable]
    public class WhyIGetConstructed
    {
        private WhyIGetConstructed()
        {
            Debug.LogError( "Why am i getting constructed, with no callstack!?" );
        }
    }

    WhyIGetConstructed _somePropertyValue = null;
}