If you’re gonna do stuff procedurally, this sorta thing can happen. Fortunately as other folks have pointed out above, there are some things you can do to mitigate against it.
However, the broad pattern I like to use when going procedural is the factory pattern. Any given component will have a static function used to Create it (or add it to an existing GameObject), in order to ensure it has what it needs without question.
Here is a trivial example of the pattern I use EVERYWHERE in my games to ensure order of initialization:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MyScript : MonoBehaviour
{
// Always call this to create MyScript objects so we know they are complete.
public static MyScript Create(
string resourcesPath,
string additionalArgument1,
int otherArgument)
{
// NOTE: only have ONE of the following two blocks of code, not both:
// Option 1:
// code for if this is a pre-defined prefab that you're going
// to load, instantiate, and then customize a bit
GameObject go = Resources.Load<GameObject>( resourcesPath);
go = Instantiate<GameObject>( go);
MyScript myScript = go.GetComponent<MyScript>();
// Option 2:
// code for making a new GameObject from scratch
//MyScript myScript = new GameObject( "MyScript.Create();").
// AddComponent<MyScript>();
// jam in the arguments we need
myScript.additionalArgument1 = additionalArgument1;
myScript.otherArgument = otherArgument;
return myScript;
}
string additionalArgument1;
int otherArgument;
void Start()
{
/// etc...
}
void Update()
{
/// etc...
}
}
This means outside of such a function you would NEVER use .AddComponent<>. And the above sample factory can be changed to accept an existing GameObject that it “installs” itself into, and correctly ensuring it has everything it needs to open up for business.
In the above case you would then call:
MyScript.Create( "Prefabs/MyPrefabForMyScript", "Arg1", 1234);
It returns the MyScript
instance it created, so if you want, keep a reference to that. Meanwhile you can be confident that MyScript has everything it needs.