Skip to content
freezy edited this page Jan 29, 2022 · 3 revisions

1 MonoBehaviour.Awake()

The very first thing that gets executed are the components' Awake() methods. These usually initialize internal values. For the playfield that's where it gets rotated. It's also the place where references to the DOTS systems are retrieved, if necessary.

For components that are not converted to entities, Awake() is where they register themselves at the player.

Note that the order in which the Awake() methods are executed is undefined and can change across runs, so you cannot rely on anything that needs to be initialized in other components, specially in the player classes.

The Player itself does a few relevant things in Awake():

  1. Instantiate a new ball manager
  2. Initialize the input manager
  3. Retrieve the GLE, and, if found, wake the lamp, coil, switch, wire and display players. These are instantiated in the constructor, so waking them means they now have a reference back to the player, the GLE, and some other instances.
  4. The physics engine gets instantiated

2 IConvertGameObjectToEntity.Convert() (DOTS Conversion)

Components that are part of the physics world get converted to entities. Here, the ECS component data is created and applied to the entity. Then, these components register with the player and the now known Entity.

3 MonoBehavior.Start()

The Start() method of the game items is not implemented by all game items. It's typically used by components that communicate with their API class and need to fetch a reference at runtime.

Through the Player, additional logic is bootstrapped, in this order:

3.1 IApi.OnInit()

All API classes that were instantiated and registered in Awake() and Convert() are now initialized. This means that during the component's Start() event method, it's undefined whether an API is initialized.

The API classes usually retrieve other API references here. For example, that's where the TroughApi gets reference to its switch and coil APIs used during runtime. It's also where it subscribes to their event emitters.

If APIs expose additional devices that don't exist as components on the playfield like coils or switches, they are also instantiated here.

Finally, the Init event is triggered, the equivalent of Visual Pinball's _Init event methods. They currently aren't used and will probably be dropped in the future.

3.2 {Coil|Lamp|Switch|Wire}Player.OnStart()

Here, the coil and lamp players subscribe to the respective events at the GLE in order to push them to the playfield components. For switches, the input handler is activated that handles key presses. In short, all the mappings are parsed and the wiring is set up accordingly.

3.3 IGamelogicEngine.OnInit()

Here the GLE typically subscribes to the driver's events. After everything is done, and the GLE has (potentially asynchronously) booted, the OnStarted event is emitted.

Registration

Registration happens in the last step for physics world objects, or in the step before for other objects. There are two goals of registration:

  1. Create the API instance of each object.
  2. Make relevant objects and API instances known to the player. The player keeps references to all APIs, and more importantly, all APIs by implementing interface. That means the player can quickly find let's say any coil API by component.

API Classes

The goal of the API classes is to gain access to game items. Should game logic once be implemented in C#, those are the interfaces that should be used to access the game items. They exist only during runtime and are made explicitly for that, which is another advantage: It eliminates any doubts which features of a class is accessible during runtime, and which only during edit time.

Currently API classes are used when components interact with each other during runtime. For example, the trough API would retrieve the drain switch's API to know when a new ball goes into the trough.

Gotchas

  • Only Awake() and Start() are globally separated. The order of which components get awaken and started first is undefined. Unity doesn't use the hierarchy order.