Start() functions order problem

Supposing I have two classes:

public class SomeClassA : MonoBehaviour
{
		public int someVariableA;
		void Start ()
		{
				someVariableA = calculate();
            }
            private int  calculate(){...}

}

public class SomeClassB : MonoBehaviour
{
		public int someVariableB;
            public SomeClassA someClassA; //Serialized, assigned in Editor
		void Start ()
		{
				someVariableB = someClassA.someVariableA;
            }
}

How do I ensure that SomeClassA’s Start() function runs before SomeClassB? I cannot use Awake() because SomeClassA depeneds already on other classes that use Awake() and needs to have them Initialized.

I can think of only 2 options: force Start() function in SomeClassA by SomeClassB? or add a boolean guard and initialize the variable in first frame of Update() function? But I think it’s not a good idea. I could add some “Init()” function in SomeClassA but then I would have to make my code more messy by addin a boolean guard in order not to initialize twice.

Could you point me in right direction?

The other option is to simply wait a frame.

IEnumerator Start(){
    yield return null;
    // Do something that relies on the other start being completed
}

Use the script execution order Look in Edit/Project Setting/Script Execution Order.

Unfortunately your easiest option is a boolean guard and Init function. I do this a lot… Unity has a script ordering feature but it’s not the best and although it says it will run scripts in Script Execution Order Settings in order for these functions (Awake, OnEnable and Update) It actually doesn’t even do that.

You could try the Script Execution Order Settings but beware… it’s not perfect. You’d be better off developing your own manager for doing this instead.

Well, first of all since you have a reference to your SomeClassA instance in your SomeClassB, why do you want to copy the value over? You can at any time use

someClassA.someVariableA

inside SomeClassB. If it’s just for initialization there are several ways:

  • In general use Awake to initialize the class itself.
  • Use Start when you have to interact with other classes. If each class initializes itself in Awake it’s ensured that they are ready when another class accesses them in Start.
  • User the execution order mechanism to specify which srcipt is handled first.
  • User lazy initialization with properties or get methods.

Example of lazy initialization:

public class SomeClassA : MonoBehaviour
{
    private int m_SomeVariableA;
    private bool m_Initialized = false;
    public int someVariableA
    {
        get
        {
            if (!m_Initialized)
                m_SomeVariableA = calculate();
            return m_SomeVariableA;
        }
        set { m_SomeVariableA = value;}
    }
    void Start ()
    {
        // // You can use this to force initialization in start if not initialized yet
        //someVariableA = someVariableA;
    }
    private int calculate(){...}
}