2
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Room : MonoBehaviour {

    public ClassB classBTestInstance = new ClassB(3);

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}

public class ClassB {
    public ClassB(int testNum) {
        Debug.Log("hello " + testNum);
    }
}

and here is the output:

enter image description here

As you can see that it says "Hello 3" twice. I wish to understand why might that be the case? I don't see where I called it twice. In image2 you will see that there is only 1 instance of room (when i attached the room class C# script to the main camera). I didn't attach this script to anything else.

enter image description here

Programmer
  • 121,791
  • 22
  • 236
  • 328
fidgetyphi
  • 928
  • 1
  • 8
  • 17

1 Answers1

12

This is really a good question. In Unity when new instance of an Object that does not inherit from MonoBehaviour is created outside a function,

1. The constructor is called from Unity's main Thread by Unity's script calling mechanism.

2. The constructor is called again but outside the Unity main Thread from a place known as the MonoBehaviour constructor. You can't even use Unity's API such as GameObject.Find("Cube"); in the constructor when that second call is made since it's made from a different Thread.


You can learn more about this by outputting the Thread id from each function call with the code below:

public class Room : MonoBehaviour
{

    public ClassB classBTestInstance = new ClassB(3);

    // Use this for initialization
    void Start()
    {
        Thread thread = Thread.CurrentThread;
        Debug.Log("Room (MainThread) Thread ID: " + thread.ManagedThreadId);
    }

    // Update is called once per frame
    void Update()
    {

    }
}

and

public class ClassB
{
    public ClassB(int testNum)
    {
        Thread thread = Thread.CurrentThread;
        Debug.Log("ClassB Constructor Thread ID: " + thread.ManagedThreadId); ;

        GameObject.Find("ok");
    }
}

SOLUTION:

Create the new instance from inside one of Unity's function such as Awake, Start instead of MonoBehaviour constructor.

public class Room : MonoBehaviour
{

    public ClassB classBTestInstance;

    // Use this for initialization
    void Start()
    {
        classBTestInstance = new ClassB(3);
    }
}
Programmer
  • 121,791
  • 22
  • 236
  • 328