Skip to main content
typo
Source Link
DMGregory
  • 141k
  • 23
  • 258
  • 401

This means the order can hop back-and-forth between GameObjects in the hierarchy, and does not necessarily process all scriotscript instances on a single object consecutively, before scripts on its child objects, etc. (This is to be expected, since we can override the order of executing particular script classes independent of how they're arranged on objects in the scene).

This means the order can hop back-and-forth between GameObjects in the hierarchy, and does not necessarily process all scriot instances on a single object consecutively, before scripts on its child objects, etc. (This is to be expected, since we can override the order of executing particular script classes independent of how they're arranged on objects in the scene).

This means the order can hop back-and-forth between GameObjects in the hierarchy, and does not necessarily process all script instances on a single object consecutively, before scripts on its child objects, etc. (This is to be expected, since we can override the order of executing particular script classes independent of how they're arranged on objects in the scene).

Rewriting with more detail and clarity.
Source Link
DMGregory
  • 141k
  • 23
  • 258
  • 401

The behaviour you mention relatingAs I mentioned in the comments, a simple way to Start is described in the documentation:

Start is called on the frame when a script is enabled just before any of the Update methods are called the first time.

You can think of this asinvestigate execution order in Unity checking, just before it calls FixedUpdate, Update, or LateUpdate onis to add a particular object, "Has this object already Started?" - if not, it calls Start "Justdebug log to each method you're interested in time", then proceeds with whatever update it was doingsomething like...

Debug.LogFormat("{0}: [Event] called on {1}'s {2} at {3}",
                 Time.frameCount,
                 name,
                 this.GetType().Name,
                 Time.time);

SoThen you can count onread the sequence of messages being called in their documented order on any one instance. Butand frame time stamps in general, it is not the case that a given MonoBehaviour message islog to find out exactly what order each method was called on all objects without any other message interleavedin.

The simplest way to seeYou'll find that this is to noticevaries between objects that you can create a new MonoBehaviour, or enable an existing one, in the middle of handling a different message. Say if I spawn an object during LateUpdate phasealready existed, enabled in your scene from the beginning of the frame, and new objects that object still needs to get its Awakecreated or enabled midway through the frame.

For script instances already present in your scene, OnEnableat load:

  1. Each script instance gets its Awake method called, then its OnEnable method, if enabled, back-to-back. Then then the next script instance gets its Awake called, so you'll see an alternating pattern of Awake OnOnable Awake OnEnable if you log it as I recommended.

    This is why these two methods are shown bundled together as "Initialization" in the Unity execution order diagram.

  2. Then all the Start methods are called, on all script instances.

  3. Then all the FixedUpdate methods for the first physics step.

  4. Then all the Update methods for the variable time step.

  5. Then all the LateUpdate methods.

For subsequent frames, Startthis process repeats for all enabled objects remaining from previous frames, starting from step 3 if there's one or more physics steps to evaluate this frame, and Update called (in that order) before its own LateUpdate can fireotherwise skipping ahead to step 4.

So when you spawn a new behaviour using Instantiate() or AddComponent()In my tests, the messages Awake and OnEnable will fire on that behaviour instance before the control flow returns from the creationorder in which particular script instances get their message method called within any given step appears to be the next statement inreverse order of creation, with the components I added last getting their method called first. I wouldn't count on this level of micro-ordering for your current messagescripts though, as it's something the engine could be expected to change when optimizing a build.

Then its FixedUpdate / Update / LateUpdate will be queuedThis means the order can hop back-up to be handled laterand-forth between GameObjects in the framehierarchy, withand Start being calleddoes not necessarily process all scriot instances on a single object consecutively, before the first of thosescripts on its child objects, if it missed the bus foretc. Start being called(This is to be expected, since we can override the order of executing particular script classes independent of how they're arranged on objects that were already in the scene).

If you're not spawning new objects midway through handling a frameIf a new script instance is spawned mid-frame, then you can count on all the already-spawned objects'with AwakeInstantiate methods running before any object'sor StartAddComponent method:

  1. Its Awake and OnEnable (if enabled) methods get called back-to-back.

  2. The Instantiate or AddComponent call returns, and control flow resumes on the next statement of the method that spawned the script, and the engine continues processing whatever message it was processing at the time.

  3. The engine moves on to the next update step (FixedUpdate, Update, LateUpdate, etc.)

    That means the new script instance has "missed the bus" for the current processing step, but can still catch the next one after this. If it was spawned during Update, it doesn't get an Update call this frame. But it could still get a LateUpdate.

  4. When the new script instance's turn comes in the next processing step (ie. FixedUpdate/Update/LateUpdate), Unity checks to see if it's been started yet. If not, it calls Start on this instance "just in time," then proceeds with processing its message method call.

  5. Just before rendering, if any newly-spawned scripts still haven't started (eg. they were spawned in LateUpdate), Unity calls Start on those stragglers.

So, etcthese newly-created or newly-enabled objects could be the reason you're observing Start or other messages sometimes getting called in the middle of some other phase of processing. But anytime you spawn something new, it needs to playIt's the engine playing catch-up to get the newly-added or -awoken instance up to speed for wherever the rest of the scene objects have advanced to in the update order.

The behaviour you mention relating to Start is described in the documentation:

Start is called on the frame when a script is enabled just before any of the Update methods are called the first time.

You can think of this as Unity checking, just before it calls FixedUpdate, Update, or LateUpdate on a particular object, "Has this object already Started?" - if not, it calls Start "Just in time", then proceeds with whatever update it was doing.

So you can count on the messages being called in their documented order on any one instance. But in general, it is not the case that a given MonoBehaviour message is called on all objects without any other message interleaved.

The simplest way to see this is to notice that you can create a new MonoBehaviour, or enable an existing one, in the middle of handling a different message. Say if I spawn an object during LateUpdate phase, that object still needs to get its Awake, OnEnable, Start, and Update called (in that order) before its own LateUpdate can fire.

So when you spawn a new behaviour using Instantiate() or AddComponent(), the messages Awake and OnEnable will fire on that behaviour instance before the control flow returns from the creation method to the next statement in your current message.

Then its FixedUpdate / Update / LateUpdate will be queued-up to be handled later in the frame, with Start being called before the first of those, if it missed the bus for Start being called on objects that were already in the scene.

If you're not spawning new objects midway through handling a frame, then you can count on all the already-spawned objects' Awake methods running before any object's Start method, etc. But anytime you spawn something new, it needs to play catch-up.

As I mentioned in the comments, a simple way to investigate execution order in Unity is to add a debug log to each method you're interested in, something like...

Debug.LogFormat("{0}: [Event] called on {1}'s {2} at {3}",
                 Time.frameCount,
                 name,
                 this.GetType().Name,
                 Time.time);

Then you can read the sequence of messages and frame time stamps in the log to find out exactly what order each method was called in.

You'll find that this varies between objects that already existed, enabled in your scene from the beginning of the frame, and new objects that get created or enabled midway through the frame.

For script instances already present in your scene, at load:

  1. Each script instance gets its Awake method called, then its OnEnable method, if enabled, back-to-back. Then then the next script instance gets its Awake called, so you'll see an alternating pattern of Awake OnOnable Awake OnEnable if you log it as I recommended.

    This is why these two methods are shown bundled together as "Initialization" in the Unity execution order diagram.

  2. Then all the Start methods are called, on all script instances.

  3. Then all the FixedUpdate methods for the first physics step.

  4. Then all the Update methods for the variable time step.

  5. Then all the LateUpdate methods.

For subsequent frames, this process repeats for all enabled objects remaining from previous frames, starting from step 3 if there's one or more physics steps to evaluate this frame, and otherwise skipping ahead to step 4.

In my tests, the order in which particular script instances get their message method called within any given step appears to be the reverse order of creation, with the components I added last getting their method called first. I wouldn't count on this level of micro-ordering for your scripts though, as it's something the engine could be expected to change when optimizing a build.

This means the order can hop back-and-forth between GameObjects in the hierarchy, and does not necessarily process all scriot instances on a single object consecutively, before scripts on its child objects, etc. (This is to be expected, since we can override the order of executing particular script classes independent of how they're arranged on objects in the scene).

If a new script instance is spawned mid-frame, with Instantiate or AddComponent:

  1. Its Awake and OnEnable (if enabled) methods get called back-to-back.

  2. The Instantiate or AddComponent call returns, and control flow resumes on the next statement of the method that spawned the script, and the engine continues processing whatever message it was processing at the time.

  3. The engine moves on to the next update step (FixedUpdate, Update, LateUpdate, etc.)

    That means the new script instance has "missed the bus" for the current processing step, but can still catch the next one after this. If it was spawned during Update, it doesn't get an Update call this frame. But it could still get a LateUpdate.

  4. When the new script instance's turn comes in the next processing step (ie. FixedUpdate/Update/LateUpdate), Unity checks to see if it's been started yet. If not, it calls Start on this instance "just in time," then proceeds with processing its message method call.

  5. Just before rendering, if any newly-spawned scripts still haven't started (eg. they were spawned in LateUpdate), Unity calls Start on those stragglers.

So, these newly-created or newly-enabled objects could be the reason you're observing Start or other messages sometimes getting called in the middle of some other phase of processing. It's the engine playing catch-up to get the newly-added or -awoken instance up to speed for wherever the rest of the scene objects have advanced to in the update order.

added 84 characters in body
Source Link
DMGregory
  • 141k
  • 23
  • 258
  • 401

The behaviour you mention relating to Start is described in the documentation:

Start is called on the frame when a script is enabled just before any of the Update methods are called the first time.

You can think of this as Unity checking, just before it calls FixedUpdate, Update, or LateUpdate on a particular object, "Has this object already Started?" - if not, it calls Start "Just in time", then proceeds with whatever update it was doing.

So you can count on the messages being called in their documented order on any one instance. But in general, it is not the case that a given MonoBehaviour message is called on all objects without any other message interleaved.

The simplest way to see this is to notice that you can create a new MonoBehaviour, or enable an existing one, in the middle of handling a different message. Say if I spawn an object during LateUpdate phase, that object still needs to get its Awake, OnEnable, Start, and Update called (in that order) before its own LateUpdate can fire.

So when you spawn a new behaviour using Instantiate() or AddComponent(), the messages Awake and OnEnable will fire on that behaviour instance before the control flow returns from the creation method to the next statement in your current message.

Then its FixedUpdate / Update / LateUpdate will be queued-up to be handled later in the frame, with Start being called just before the first of those, if it missed the bus for Start being called on objects that were already in the scene.

If you're not spawning new objects midway through handling a frame, then you can count on all the already-spawned objects' Awake methods running before any object's Start method, etc. But anytime you spawn something new, it needs to play catch-up.

The behaviour you mention relating to Start is described in the documentation:

Start is called on the frame when a script is enabled just before any of the Update methods are called the first time.

You can think of this as Unity checking, just before it calls FixedUpdate, Update, or LateUpdate on a particular object, "Has this object already Started?" - if not, it calls Start "Just in time", then proceeds with whatever update it was doing.

So you can count on the messages being called in their documented order on any one instance. But in general, it is not the case that a given MonoBehaviour message is called on all objects without any other message interleaved.

The simplest way to see this is to notice that you can create a new MonoBehaviour, or enable an existing one, in the middle of handling a different message. Say if I spawn an object during LateUpdate phase, that object still needs to get its Awake, OnEnable, Start, and Update called (in that order) before its own LateUpdate can fire.

So when you spawn a new behaviour using Instantiate() or AddComponent(), the messages Awake and OnEnable will fire on that behaviour instance before the control flow returns from the creation method to the next statement in your current message.

Then its FixedUpdate / Update / LateUpdate will be queued-up to be handled later in the frame, with Start being called just before the first of those.

If you're not spawning new objects midway through handling a frame, then you can count on all the already-spawned objects' Awake methods running before any object's Start method, etc. But anytime you spawn something new, it needs to play catch-up.

The behaviour you mention relating to Start is described in the documentation:

Start is called on the frame when a script is enabled just before any of the Update methods are called the first time.

You can think of this as Unity checking, just before it calls FixedUpdate, Update, or LateUpdate on a particular object, "Has this object already Started?" - if not, it calls Start "Just in time", then proceeds with whatever update it was doing.

So you can count on the messages being called in their documented order on any one instance. But in general, it is not the case that a given MonoBehaviour message is called on all objects without any other message interleaved.

The simplest way to see this is to notice that you can create a new MonoBehaviour, or enable an existing one, in the middle of handling a different message. Say if I spawn an object during LateUpdate phase, that object still needs to get its Awake, OnEnable, Start, and Update called (in that order) before its own LateUpdate can fire.

So when you spawn a new behaviour using Instantiate() or AddComponent(), the messages Awake and OnEnable will fire on that behaviour instance before the control flow returns from the creation method to the next statement in your current message.

Then its FixedUpdate / Update / LateUpdate will be queued-up to be handled later in the frame, with Start being called before the first of those, if it missed the bus for Start being called on objects that were already in the scene.

If you're not spawning new objects midway through handling a frame, then you can count on all the already-spawned objects' Awake methods running before any object's Start method, etc. But anytime you spawn something new, it needs to play catch-up.

Source Link
DMGregory
  • 141k
  • 23
  • 258
  • 401
Loading