docs
Systems
Infrastructure
UpdateSystem
Architecture

title: Architecture and Design order: 2 source: generated

Design patterns in use

  • Adapter. IUpdateAdapter is the contract that bridges an engine heartbeat to the pure C# manager. UnityUpdateAdapter is the Unity implementation.
  • Template Method. UpdateAdapter.Initialize performs the null guard and then calls the abstract OnInitialized hook, which subclasses implement.
  • Command message. Registration is a Command envelope with a verb from UpdateCommandVerb and typed params. UpdateManager.ProcessCommand switches on the verb.
  • Static factory. UpdateCommandFactory builds and sends commands so callers do not construct them directly.

How it connects to other systems

  • Contracts. UpdateCommandFactory creates commands with Domain.Update. UpdateFlowController overrides Domain to return Domain.Update, so the bus routes Update-domain commands to it.
  • Params. The registration payload is stored under UpdateKeys.UpdateableObject, a ParamKey whose name is built from UpdateKeyNames. UpdateFlowController.HandleCommand checks for that key with Has before forwarding the command.
  • Commands. Commands are created with Command.Create and sent through BusUtility.Send.
  • Flow. UpdateFlowController inherits FlowController. Its Init calls base.Init(), which registers HandleCommand on the command bus for its domain.

Key concepts

  • Tick. One invocation of the private UpdateManager.Tick, which calls OnUpdate on every registered object in registration order.
  • Adapter binding. The link created by SetUpdateAdapter, which calls Initialize with the manager's Tick as the callback.
  • Registry. The updateables list. Registration skips null and duplicate references.
  • PlayerLoop injection. The process by which UpdateService finds the target phase node and appends a system node that runs the tick.

Data and control flow

Startup

  1. UpdateFlowController.Init calls base.Init(), registering HandleCommand for Domain.Update.
  2. It creates an UpdateManager and a UnityUpdateAdapter, then calls SetUpdateAdapter.
  3. SetUpdateAdapter stores the adapter and calls Initialize(Tick).
  4. UpdateAdapter.Initialize calls OnInitialized(onTick).
  5. UnityUpdateAdapter.OnInitialized calls UpdateService.InjectToPlayerLoop<UnityUpdateAdapter, UnityEngine.PlayerLoop.Update>.
  6. UpdateService wraps the action in a PlayerLoopSystem. UpdateUtility.TryInsertSystem searches the loop tree for the Update phase and appends the node. If the phase is found, PlayerLoop.SetPlayerLoop applies the new loop.

Registration

  1. A caller invokes UpdateCommandFactory.RegisterUpdatable(updateable).
  2. The factory creates a Register command for Domain.Update, sets UpdateKeys.UpdateableObject in its params, and calls BusUtility.Send.
  3. The command bus delivers the command to UpdateFlowController.HandleCommand.
  4. If the key is present, UpdateManager.ProcessCommand runs. For Register, it calls AddUpdateable, which adds the object if it is not already in the list.

Tick

  1. Unity's Update phase runs the injected delegate.
  2. The delegate calls the manager's Tick.
  3. Tick loops over updateables and calls OnUpdate on each.

Behaviour and limits visible in the code

  • The registry is only added to.
  • Tick enumerates updateables with foreach. Because the code has no guard, an OnUpdate implementation that registers another object during a tick would modify the list while it is being enumerated.
  • UpdateService appends each injected system to the PlayerLoop.

Initialization order

UpdateFlowController.Init calls base.Init() before it creates updateManager. The base method registers HandleCommand on the bus.

Adapter replacement

SetUpdateAdapter replaces the stored adapter and calls Initialize again. The code does not remove any earlier PlayerLoop injection.