Any reason for a difference in execution order for Begin Play calls?

The execution order seems to change between Editor and Build which can cause scenarios where you can get an error in PIE In Editor, make a fix, and cause the Build to break.

Elaborating

We have training lessons split up into their own levels and the Level Begin Play interacts with a Widget created by the Player Controller’s Begin Play. In Editor, we receive errors because the Level loads before Player Controller causing NULL values (unless we delay the Level Begin Play in some way).

Since the Level Loads first and I assigned an Event from the Level Blueprint to an Event Dispatcher on the Player Controller called “Ready” for it to call at the end of Begin Play. In the Build, this caused our lesson to break because the Controller loaded first and called “Ready” but the Level had not assigned the Event yet (and there was no way to call the Dispatcher again).

I found a solution that worked for us, but I was curious if there is a particular reason that the Execution Order is different? I didn’t have time to go exploring the Engine code and hoped maybe someone more versed in its construction could explain it to me, or perhaps it was totally unintentional. More info about what I found after testing down below.


I have only been able to test this so far on Windows and In Editor (currently working on testing for Mobile). I also have not been able to test on machines of variable speeds (maybe slower processors would have different results).


Computer Specs (not sure if this is needed but describing my test scenario)

OS: Win 7 Enterprise 64-bit

CPU: i7-6700K 4.00GHz (8 CPUs)

RAM: 32GB

GPU: GeForce GTX 970 w/ 4GB Video Memory


The execution order for Begin Play in Editor

  1. Actor in Level
  2. Game Mode
  3. Level
  4. Game State
  5. Player Controller
  6. Player State
  7. HUD
  8. Pawn

Begin Play in Built Game

  1. Pawn
  2. Game Mode
  3. Game State
  4. Player State
  5. Player Controller
  6. HUD
  7. Level
  8. Actor in Level

1 Like

Good question. And you actually took the time to take this apart. I had to learn this the hard way.

While this won’t answer all your questions and I’m nowhere nearly knowledgeable enough to detail the why here, please do consider having a look at the following link:

Hopefully this will shed a bit of light on this behaviour.

Thanks for that link it explained a little bit, like why Actors in the Level are first in Editor and last in a Build / Standalone. There are a bunch of other unexpected orders too.

Pawn swaps between being “least important” to “most important” (opposite the Actors) which re-organizes Pawn → Player Controller. Player State and Player Controller flip so you can’t rely on Begin Play interactions between those. Level moves from 3rd to nearly last, and nothing can really access the level but can cause broken interactions with the level if it’s assigning events to delegates.

I know you said you can’t answer the why. I’m elaborating in-case someone comes by who could.


Also, for anyone who comes by seeking a solution to this (wanting to remove errors and not break things) my (feels kinda hacky) solution:

Explanation: I added a boolean value so I could test whether or not Begin Play had already completed. If it is true, the level can call the function/event whenever it wants because the Controller should be ready to go. If it is false, the level binds that function/event to a Delegate on the Controller so the controller can tell the Level when it’s done.

I tend to use a single Begin Play in Game Mode, that’s it (apart from dynamically spawned objects, that is). That’s my info hub that sets everything else up, registers some of the main dispatchers, some direct references, spawns helper classes and so on.

Never had to look back at the order again.

3 Likes

BeginPlay is called on creation of actor in play mode just after InitlizeComponents, so what you see is effectivly order of object creation and because Play In Editor is using some hackish world instance swamping order of creation can be different.

This is a good approach in my opinion. Leaves no room for errors.

I’m curious what you are doing with the game mode? Are you having different game modes for each level? In your mind what is game mode’s place in the hierarchy of the game logic?
Curious because I think I must have had a different understanding of it’s role and I want to understand and correct my own understanding as needed!