Table of Contents

Programming Notes

Built-in Callbacks

Once

The :Once function was create to simplify this pattern

once
   # do stuff once
endonce

once/endonce was created to simplify this pattern

if (<-hasRun !)
   true ->hasRun
   # do stuff once
endif

In other words, both of these are equivalent to an if statement with the variable managed internally.

On the first “update” of a script the once callback will be called. So this happens before the first call to the script, but after the game is unpaused. The status variable that tracks if :Once has been called gets set at this time. That means if you manually call :Once in :Awake or :GameLoaded, it will get called again on the first run of the script.1)

Note: The internal status variable for each once in your code is implemented as an array of bools. The position of the once command in the compiled code is the position in the once array. Upon execution of a once, it's status variable in the array is set to true.

Awake

For units, this happens at the end of the load process when a Unit is being loaded from a save. When a unit is being created during a mission it happens at the end of that creation process right after the script is compiled. For global scripts, it happens on the first frame (ignoring game paused status). That will be at the top or bottom of the frame depending on if the global script is set to pre or post. In other words, :Awake happens very soon after any script is instantiated.

For Global Control scripts, :Awake runs during a game frame, either before units are processed (for the Pre- phase) or after units are processed (for the Post- phase). Here, both :Awake and :Once run alongside each other, and depending on whether the script is marked to run while paused or not, both of them will run either during a paused frame or an unpaused frame. Because of this, :Awake in Global Control scripts will always run after :Awake in units. Key difference between :Awake and :Once remains where :Awake will run again when the map is loaded, but :Once will not.

GameLoaded

Gets called for pre global scripts, unit, and post global scripts (in that order) at the top of the first (and only first) frame after a game is loaded. So this is after units are loaded, but before any game logic has executed. It happens once and only once per game load. Launching a mission counts as a “load”.

Awake and Once in Unit and Global Control scripts

Execution order of Global Control scripts which run while paused:

Execution order of Global Control scripts which do not run while paused:

Technical explanation

A critical distinction exists between scripts attached to units and scripts scheduled to run during Pre- or Post- phases of Global Control.

Functionally, the :Awake function in pre- or Post Global Control phases are equivalent to the :Once function. It is not executed until the appropriate moment in processing (before or after all units are processed for every game tick). This may cause execution of :Awake functions to appear in the incorrect order, where each unit will execute it's :Awake function as it is instantiated during map load (either initial load or load from a save, there is no difference), and the :Awake in a Global Control script will execute at the beginning or end, respectively, of a game tick.

1)
I have not verified this… it just looks like it will be the case. This probably wasn't intentional, I just never thought about calling :once from :awake. I don't think it is strictly necessary to ever do so, but still…
knucracker