|
|
@@ -17,37 +17,43 @@ The application then enters the update loop where the application will spend the
|
|
|
|
|
|
At some point, the application's lifecycle will come to an end. Before the application quits the engine steps out of the update loop and enters a finalization stage. It prepares all loaded game objects for deletion. All object components’ [`final()`](/ref/go#final) functions are called, which allows for custom cleanup. Then the objects are deleted and the main collection is unloaded.
|
|
|
|
|
|
+The steps involved in the ["dispatch messages"](#dispatching-messages) pass are shown in a separate diagram at the end of this manual for clarity and are marked in diagrams with a small "envelope with an arrow" icon 📩.
|
|
|
+
|
|
|
## Initialization
|
|
|
|
|
|
-This is the first step of the running game:
|
|
|
+This is were your game starts and is the first step of the running game. It can be separated into 3 phases:
|
|
|
|
|
|

|
|
|
|
|
|
-This diagram contains a more detailed breakdown of the initialization steps, that can be separated into 3 main phases. The steps involved in the "dispatch messages" pass are shown in a separate diagram below for clarity and are marked in diagrams with a small "envelope with an arrow" icon 📩.
|
|
|
-
|
|
|
-
|
|
|
+### Pre Init
|
|
|
|
|
|
During `Pre Init` phase, the engine takes many steps, before the main (bootstrap) collection is loaded. The memory profiler, sockets, graphics, HID (input devices), sound, physics and much more are set up. The application configuration (*game.project*) is also loaded and set up.
|
|
|
|
|
|
+
|
|
|
+
|
|
|
The first user-controllable entry point, at the end of engine initialization, is the call to the current render script’s `init()` function.
|
|
|
|
|
|
The main collection is then loaded and initialized.
|
|
|
|
|
|
-
|
|
|
+### Collection Init
|
|
|
|
|
|
During the `Collection Init` phase, all game objects in the collection apply their transforms (translation (change of position), rotation and scaling) to their children. All component `init()` functions that exist are then called.
|
|
|
|
|
|
+
|
|
|
+
|
|
|
::: sidenote
|
|
|
The order in which game object component `init()` functions are called is unspecified. You should not assume that the engine initializes objects belonging to the same collection in a certain order.
|
|
|
:::
|
|
|
|
|
|
-
|
|
|
+### Post Update in Initialization
|
|
|
|
|
|
-Since your `init()` code can post new messages, tell factories to spawn new objects, mark objects for deletion and perform many other actions, the engine performs a full `Post Update` pass next. This is the same pass that is performed after each `Update Loop` step.
|
|
|
+The engine then performs a full `Post Update` pass - the same pass that is performed after each `Update Loop` step later on. It is performed at the end of intialization, because your `init()` code can post new messages, instruct factories to spawn new objects, mark objects for deletion, and perform other actions.
|
|
|
|
|
|
-This pass carries out message delivery, the actual factory game object spawning and object deletion. Note that the post-update pass includes a "dispatch messages" sequence that not only sends any queued messages but also handles messages sent to collection proxies. Any subsequent updates on the proxies (enable and disable, loading and mark for unloading) are performed during those steps.
|
|
|
+
|
|
|
+
|
|
|
+This pass carries out message delivery, actual factory game object spawning, and object deletion. Note that the `Post Update` pass includes a "dispatch messages" sequence that not only delivers queued messages, but also processes messages sent to collection proxies. Any subsequent proxy updates (enable, disable, loading, and mark for unloading) are performed during those steps.
|
|
|
|
|
|
-Studying the diagram above reveals that it is entirely possible to load a [collection proxy](/manuals/collection-proxy) during `init()`, ensure all its contained objects are initialized, and then unload the collection through the proxy - all this before the first component `update()` is called, i.e. before the engine has left the initialization stage and entered the update loop:
|
|
|
+It is entirely possible to load a [collection proxy](/manuals/collection-proxy) during `init()`, ensure all its contained objects are initialized, and then unload the collection through the proxy - all this before the first component `update()` is called, i.e. before the engine has left the initialization stage and entered the update loop:
|
|
|
|
|
|
```lua
|
|
|
function init(self)
|
|
|
@@ -72,26 +78,9 @@ function on_message(self, message_id, message, sender)
|
|
|
end
|
|
|
```
|
|
|
|
|
|
-## Dispatching Messages
|
|
|
-
|
|
|
-After **each** component-type update and any other action that may send messages during its execution all posted messages are dispatched. Those are marked in the diagrams with small "envelope with an arrow" icons 📩.
|
|
|
-
|
|
|
-Since any receiver components’ `on_message()` code can post additional messages, the message dispatcher will continue to dispatch posted messaged recursively until the message queue is empty. There is, however, a limit to how many runs through the message queue the message dispatcher performs. See [Message Chains](/manuals/message-passing#message-chains) for details.
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-After all **user messages** are dispatched by calling `on_message()` for each component, Defold special messages are handled in the following order (as presented in the diagram too), for each collection proxy:
|
|
|
-
|
|
|
-1. `load` messages - to load collection proxies marked for loading, posts back `proxy_loaded` message.
|
|
|
-2. `unload` messages - to unload collection proxies marked for unloading, posts back `proxy_unloaded` message.
|
|
|
-3. `init` messages - triggers the `Collection Init` phase for all collection proxies to be initialized.
|
|
|
-4. `final` messages - triggers `final()` on all components of the proxy marked to be finalized.
|
|
|
-5. `enable` messages - enables the collection proxy, so the `Update Loop` will be performed for it in the next frame; this implicitly triggers `init()` for each component of the collection.
|
|
|
-6. `disable` messages - disables the colleciton proxy, so the `Update Loop` will **not** be performed for it in the next frame; it stops running `Update Loop` for it completely.
|
|
|
-
|
|
|
## Update Loop
|
|
|
|
|
|
-The update loop runs through a specific sequence once per frame. This sequence can be defined by 5 main phases:
|
|
|
+The Update Loop runs through a specific sequence once per frame. This sequence can be defined by 5 main phases:
|
|
|
|
|
|

|
|
|
|
|
|
@@ -101,7 +90,7 @@ The update loop runs through a specific sequence once per frame. This sequence c
|
|
|
4. Post Update (unloading collection proxies, spawning and deleting game objects)
|
|
|
5. Frame Render (final graphics are rendered)
|
|
|
|
|
|
-## Input Phase
|
|
|
+### Input Phase
|
|
|
|
|
|
Input is read from available devices, mapped against [input bindings](/manuals/input) and then dispatched. Any game object that has acquired input focus gets input sent to all its components' `on_input()` functions. A game object with a script component and a GUI component with a GUI script will get input to both components’ `on_input()` functions - given that they are defined and that they have acquired input focus.
|
|
|
|
|
|
@@ -109,13 +98,15 @@ Input is read from available devices, mapped against [input bindings](/manuals/i
|
|
|
|
|
|
Any game object that has acquired input focus and contains collection proxy components dispatches input to components inside the proxy collection. This process continues recursively down enabled collection proxies within enabled collection proxies.
|
|
|
|
|
|
-## Update Phase
|
|
|
+### Update Phase
|
|
|
+
|
|
|
+The `Update` phase is a part of the Update Loop. It is started once for the root collection, and then runs recursively for each enabled collection proxy.
|
|
|
|
|
|
-The `Update` phase is a part of the Update Loop that is started for the root collection and recursively called for each collection proxy. During the `Update` phase the Lua callbacks are called in the order in loops for each component type (usually script):
|
|
|
+Within a collection, Defold processes callbacks by a component type that implements Lua callbacks (most commonly script components): it iterates over all of them and calls the relevant Lua callback on each of them, then moves on to the next callback stage. The callback stages order is:
|
|
|
|
|
|
-1. `fixed_update()` x 0..N (if using fixed timestep)
|
|
|
-2. `update()` x 1
|
|
|
-3. `late_update()` x 1
|
|
|
+1. `fixed_update()` - called 0..N times per frame (if using fixed timestep)
|
|
|
+2. `update()` - called 1 time per frame
|
|
|
+3. `late_update()` - called 1 time per frame
|
|
|
|
|
|

|
|
|
|
|
|
@@ -126,21 +117,19 @@ Each game object component in the main collection is traversed. If any of these
|
|
|
The order in which game object component `update()` functions are called is unspecified. You should not assume that the engine updates objects belonging to the same collection in a certain order. The same is true for `fixed_update()` and `late_update()` (since 1.12.0).
|
|
|
:::
|
|
|
|
|
|
-### Physics
|
|
|
+#### Physics
|
|
|
|
|
|
For collision object components, physics messages (collisions, triggers, ray_cast responses etc) are dispatched throughout the encompassing game object to all components that contain a script with an `on_message()` function.
|
|
|
|
|
|
-::: sidenote
|
|
|
If a [fixed timestep](/manuals/physics/#physics-updates) is used for physics simulation, there may also be a call to the `fixed_update()` function in all script components. This function is useful in physics based games when you wish to manipulate physics objects at regular intervals to achieve a stable physics simulation.
|
|
|
-:::
|
|
|
|
|
|
-### Transforms
|
|
|
+#### Transforms
|
|
|
|
|
|
-Before **each** component-type update, the transforms are updated if needed, applying any game object movement, rotation and scaling to each game object component and any child game object components.
|
|
|
+Before **each** component-type update, multiple times during the `Update Loop`, if needed, the transforms are updated, applying any game object movement, rotation and scaling to each game object component and any child game object components.
|
|
|
|
|
|
-There is one additional final transforms update at the end, if needed.
|
|
|
+There is one additional final transforms update at the end of the `Update Loop`, if needed.
|
|
|
|
|
|
-### Engine Update Phase
|
|
|
+#### Engine Update Phase
|
|
|
|
|
|
When `Use Fixed Timestep` is `false`, at the beginning of the phase it prepares `dt` and then loops:
|
|
|
|
|
|
@@ -155,7 +144,7 @@ Note that after each component type update, all messages are dispatched - this i
|
|
|
| 3 | **Late Update** | `late_update()` | Called once per frame. For each component type that implements late update in the priority order. |
|
|
|
| 4 | **Transforms** | | One additional final transforms update is performed at the end for each component if needed. |
|
|
|
|
|
|
-### Engine Update Phase with Fixed Timestep
|
|
|
+#### Engine Update Phase with Fixed Timestep
|
|
|
|
|
|
When `Use Fixed Timestep` is `true`, at the beginning of the phase it prepares `dt`, `fixed_dt` and `num_fixed_steps` (`0..N`) - so how many times fixed update will be called and then loops:
|
|
|
|
|
|
@@ -174,13 +163,13 @@ Note that after each component type update, all messages are dispatched - this i
|
|
|
|
|
|
If you ever need more details on how Defold works internally during the Update phase, it is worth reading the [`gameobject.cpp`](https://github.com/defold/defold/blob/dev/engine/gameobject/src/gameobject/gameobject.cpp) code itself.
|
|
|
|
|
|
-## Render Update Phase
|
|
|
+### Render Update Phase
|
|
|
|
|
|
The render update block dispatches first all messages sent to the `@render` socket (e.g. camera component `set_view_projection` messages, `set_clear_color` messages etc). The render script `update()` is then called.
|
|
|
|
|
|

|
|
|
|
|
|
-## Post update Phase
|
|
|
+### Post update Phase
|
|
|
|
|
|
After the updates, a post update sequence is run. It unloads from memory collection proxies that are marked for unloading (this happens during the "dispatch messages" sequence). Any game object that is marked for deletion will call all of its components’ `final()` functions, if there are any. The code in `final()` functions often posts new messages to the queue so a "dispatch messages" pass is run afterwards.
|
|
|
|
|
|
@@ -188,7 +177,7 @@ After the updates, a post update sequence is run. It unloads from memory collect
|
|
|
|
|
|
Any factory component that has been told to spawn a game object will do that next. Finally, game objects that are marked for deletion are actually deleted.
|
|
|
|
|
|
-## Render Phase
|
|
|
+### Render Phase
|
|
|
|
|
|
The last step in the update loop involves dispatching `@system` messages (`exit`, `reboot` messages, toggling the profiler, starting and stopping video capture, etc.).
|
|
|
|
|
|
@@ -196,7 +185,7 @@ The last step in the update loop involves dispatching `@system` messages (`exit`
|
|
|
|
|
|
Then graphics are rendered, as is any rendering of the visual profiler (see the [Debugging documentation](/manuals/debugging)). After the graphics rendering, a video capture is done.
|
|
|
|
|
|
-## Frame rate and collection time step
|
|
|
+#### Frame rate and collection time step
|
|
|
|
|
|
The number of frame updates per second (which equals the number of update-loop runs per second) can be set in the project settings, or programmatically by sending a `set_update_frequency` message to the `@system` socket. In addition, it is possible to set the _time step_ for collection proxies individually by sending a `set_time_step` message to the proxy. Changing a collection's time step does not affect the frame rate. It does affect the physics update time step as well as the `dt` variable passed to `update().` Also note that altering the time step does not alter the number of times `update()` will be called each frame --- it is always exactly once.
|
|
|
|
|
|
@@ -215,3 +204,20 @@ Component `final()` functions are called first. A subsequent dispatching of mess
|
|
|
The engine then proceeds with behind-the-scenes shutting down of subsystems: project configuration is deleted, the memory profiler is shut down, and so forth.
|
|
|
|
|
|
The application is now completely shut down.
|
|
|
+
|
|
|
+## Dispatching Messages
|
|
|
+
|
|
|
+**Dispatching Messages** is a special pass that is performed after each **each** component-type update and any other action that may send messages during its execution all posted messages are dispatched. Those are marked in the diagrams with small "envelope with an arrow" icons 📩.
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+After all **user messages** are dispatched by calling `on_message()` for each component, Defold special messages are handled in the following order (as presented in the diagram too), for each collection proxy:
|
|
|
+
|
|
|
+1. `load` messages - to load collection proxies marked for loading, posts back `proxy_loaded` message.
|
|
|
+2. `unload` messages - to unload collection proxies marked for unloading, posts back `proxy_unloaded` message.
|
|
|
+3. `init` messages - triggers the `Collection Init` phase for all collection proxies to be initialized.
|
|
|
+4. `final` messages - triggers `final()` on all components of the proxy marked to be finalized.
|
|
|
+5. `enable` messages - enables the collection proxy, so the `Update Loop` will be performed for it in the next frame; this implicitly triggers `init()` for each component of the collection.
|
|
|
+6. `disable` messages - disables the colleciton proxy, so the `Update Loop` will **not** be performed for it in the next frame; it stops running `Update Loop` for it completely.
|
|
|
+
|
|
|
+Since any receiver components’ `on_message()` code can post additional messages, the message dispatcher will continue to dispatch posted messaged recursively until the message queue is empty. There is, however, a limit to how many runs through the message queue the message dispatcher performs. See [Message Chains](/manuals/message-passing#message-chains) for details.
|