Hey everyone, so I’m having a really weird issue with the execution of the Start() and Update() functions in two different scripts on the same object.
Basically, I have two scripts with Start(). The expected behavior is that Start() for both scripts would be executed before Update() is on either object. And it behave like this, about 50% of the time. The other 50% however, Start() in Script A is executed, and then Update() in Script A is executed. THEN after Update() in Script A, Start() in Script B is executed.
Like I said, this happens what seems to be randomly, as I can see nothing being done to cause this on my end. No yield returns, and the issue happens in the same context, which is on loading a scene.
The way I tested this was by having a static class with a static int. In Script A Start(), Script B Start(), and Script A Update() I increase the int by one and print it out.
static class MyStaticClass
{
static int DebugInt = 0;
}
class ScriptA
{
void Start () {
MyStaticClass.DebugInt += 1;
print(MyStaticClass.DebugInt);
}
void Update () {
MyStaticClass.DebugInt += 1;
print(MyStaticClass.DebugInt);
}
}
class ScriptB
{
void Start () {
MyStaticClass.DebugInt += 1;
print(MyStaticClass.DebugInt);
}
}
Output:
1 // ScriptA Start()
2 // ScriptA Update()
3 // ScriptB Start()
So I’m not sure at this point if I’m just being stupid or what, but this is not something I want to spend all my time figuring out on my own. I’m not even like a beginner with C# in unity, which is what’s making this all the more confusing for me. Anyways, any advice is appreciated, and thanks in advance for the help.
Alright, so the issue is that I am instantiating a prefab instead of it being an object already placed in and serialized in the scene. Even if I am instantiating both objects at the same time, the Update function will be called immediately after the Start function in that MonoBehaviour, before moving onto the next MonoBehaviour to call its Start function.
This would not be the case however if the objects are already serialized in the scene before when the scene loads. For functions like Awake() and OnEnable(), those will always be called one step at a time, as would be expected.
So to clarify:
With the exception of a few unique cases, Unity does a step of the execution cycle for all applicable MonoBehaviours before it moves onto the next step for any other MonoBehaviour.
I won’t bother linking to the manual for execution order since it’s already been done a couple of times here. The language can be a little confusing (it confused me) but it does say that for Start’s definition that it operates differently based off of whether or not it is instantiated or pre-placed.
Anyways, thanks for all the help and input guys, it’s always good to hear different thoughts on an issue.
The Start function is called before Update for the same MonoBehaviour. That does not imply that all the Start functions is called before all the Update functions for all MonoBehaviour.
Start is called on the frame when a script is enabled just before any of the Update methods is called the first time.
Though this sentence is not very explicit.
If you want script A to run before script B, you have to specify their execution order, see:
All Start methods normally are called before any Update method. However, Start is not called if an object is disabled. If you are enabling an object in the Start of another script, that could cause this behavior (I think).
This is already an old post, but reading this and experiencing the same, I conclude that Start()/Update() behaviour in Unity is different for prefabs (or gameobject trees enabled later in the scene), than gameobjects that already exist and are enabled in the scene. Given that a) its behaviour is not deterministic and b) that it is completely not as expected, I think this can very well be considered a Unity bug. And also a nasty one, because this means that the app behaviour can be different when you start converting parts of you hierarchy into prefabs, say when you are tidying up things.
However, the desired effect is achievable through LateUpdate(). This will only be called once all Update()'s are called and thus all Start()'s are called