In base class, Inspector initialized variable returns null when trying to access it in child class' Start method

Here is my simplified base class

public class BuildingScript : MonoBehaviour {
    public CityHallScript CityItBelongsTo;


}

And my simplified child class

public class EnergyGeneratorScript : BuildingScript {
    public override void Start () {

        base.Start();
        CityItBelongsTo.CityHall.City.cityResources.RaiseLimit(resource, amount);

    }
}

I have a gameobject called “HQ” in my scene and has a “CityHallScript” attached to it and i gave this to inspector variable for “CityItBelongsTo”. RaiseLimit method DOES work on BuildingScript start function no problem, but when i try it on EnergyGeneratorScript “CityItBelongsTo” is null. Weird thing is that when i try RaiseLimit method in Update function in EnergyGeneratorScript it DOES work, so i am guessing this happens because when if i call RaiseLimit method in Start method, CityItBelongsTo isnt initialized yet. Right now my workaround is i made a bool variable called “init” and made an if condition in Update function that if init is true i call RaiseLimit method and change init to false. So any ideas how to make this right ? Thanks.

This is part of the general subject of synchronization of initialization. There’s Unity, and then there’s all other software engineering in all languages.

Unity has a configuration for the order of Script Execution Order. This can patch your problem, but I don’t recommend this approach. There isn’t a problem using this approach, but my own background is that of software engineering, and I know that using an external tool to fix a synchronization problem in this way actually leaves the problem in the code. It is patched or fixed to work by this configuration, and it can be a quick way of solving the problem, but it isn’t a solution.

A solution would eliminate the problem so that the Script Execution Order method isn’t even needed. For a study project, some minor builds, my point may seem overkill. My underlying point, though, is that even while learning (maybe especially), one should develop engineering habits which don’t produce problems to be solved with something like execution order configuration from the editor.

It may be that you can break initialization into two different stages, and use Awake() for the prerequisite initialization, and Start will continue to do everything else. Unity docs state that all Awakes are called (and finished) before any Starts are executed. This means you should be able to fashion the solution in code, so that Script Execution Order isn’t even needed.

This also means that if you establish the habit of designing initialization with synchronized phases, you’ll never need to have Unity edit the order, and your code will be portable (that is, you can re-use classes that may be designed for generic use everywhere).

Your use of the bool represents the more general “design pattern” (if it was ever so formalized) known as lazy initialization, and is a valid solution generally for making sure a prerequisite initialization is done.