Script Execution Order Not Working As Documented?

I’m moving an old game of mine from Unity 5.6 over to 2019.3.6f1 and am running into problems with script execution order all of a sudden. I’m running into two problems at the moment:

  1. All Awake() functions should be called before all Start() functions. I am seeing a case where this is not happening.

  2. Script execution order should determine when Awake() functions are called. Again, I am seeing a case where this is not happening.

I have 3 scripts set up in script execution order as follows: A, B, C, where A is first, B is second, and C is third in script execution order. Here’s my understanding of how the Awake() and Start() flow should work in this case:

  1. A-Awake()
  2. B-Awake()
  3. C-Awake()
  4. A-Start()
  5. B-Start()
  6. C-Start()

Isn’t that how it’s supposed to work? With the Visual Studio 2017 debugger, here’s what I’m actually seeing on Unity 2019.3.6f1:

  1. A-Awake() (Correct)
  2. C-Awake() (Wrong. This should be B-Awake)
  3. C-Start() (Wrong for 2 reasons: First, all Awake() functions have not been called before any Start() functions. Second, it’s calling functions on C instead of B.

C is a UI script that I figure could potentially be started by the Unity Event System, but I have placed all these before that system in the script execution order, so I don’t know what’s going on here. Is this a bug or have I misunderstood the documention? This works fine in Unity 5.6 but in 2019 it’s different and I see no rhyme or reason to it.

A little more info: A’s Awake() function instantiates an object that has component B. Is it possible that B Awake() isn’t called until the next cycle in 2019?

Are all of these objects present and enabled in the scene hierarchy when the scene loads? Are any of them instantiated at runtime? Ar B - Awake() and B - Start() ever getting called?

2 Likes

As per the documentation, https://docs.unity3d.com/ScriptReference/Object.Instantiate.html, Awake and OnEnable should get called as you Instantiate it, regardless of any Script Execution Order settings (assuming the object it is being cloned from is active), which should be part of Object A’s Awake() method. is the prefab you are instantiating “B” from Active (Is the checkbox at the top left of the inspector checked?).

1 Like

All are enabled, but they’re not all present when the scene loads. A and C are present, but B is not. B is a component on a prefab instantiated by A’s Awake() function, but somehow B’s Awake() isn’t being called before C’s Start() function. I would expect B’s Awake function to be called before any Start() functions since the prefab instantiation is happening immediately when the scene loads before virtually everything else, but maybe Unity 2019 doesn’t work this way?

I’m wondering if it works out like this in 2019:

  1. A-Awake() → Instantiate B
  2. C-Awake()
  3. C-Start()

Then on the next cycle:
4) B Awake()
5) B Start()

I can’t verify if this is happening though because this breaks the game before B’s Awake() function is ever even called (let alone B’s Start()), so it doesn’t even make it that far. I would expect B-'s Awake() to be called as soon as it’s instantiated, before it’s moved on to the Start() functions, but that’s not happening. The only thing I can think is maybe it’s moved to the next frame, but by then it’s too late. It breaks the entire design.

I’m running into quite a few problems of this nature that I didn’t have in Unity 5.6, unfortunately. This system worked flawlessly there and the game’s been sitting up on Steam for a few years already. In the years since on other projects, I’ve moved to having scene managers with just one Awake() and one Start() in each scene where possible so I can exactly control the order in which everything occurs, but this is a game from 4-5 years ago that I’m trying to add multiplayer to that used the typical pattern of its time. If I have to gut the entire code base to get around some changes like this that might have happened between Unity 5 and Unity 2019, it’s probably not worth adding multiplayer.

No. Neither one gets called, but that’s probably because it’s snowballed into a total meltdown before that can happen. Maybe it would happen on the next frame, I don’t know, but it has to happen on the first frame in the right order or it’ll go boom. There’s a whole mess of setting up references to the instantiated game object, doing things in a particular order that gets blown up if B Awake() doesn’t called called exactly where it’s supposed to:

A Awake() instantiates B, B Awake() runs, then C Awake().

Not A Awake() and then C Awake() and then C Start() with no B Awake(). :face_with_spiral_eyes: