Game.GameSystemBase
Assembly: Assembly-CSharp
Namespace: Game
Type: abstract class
Base: COSystemBase
Summary:
GameSystemBase is a reusable abstract base class for game systems in Cities: Skylines 2. It wires a system into core game lifecycle events (GameManager and load/save events) and provides safe exception handling around those callbacks. It also integrates with the Entities world to obtain the LoadGameSystem when running in the default DOTS world, and offers small helpers such as ResetDependency and configurable update interval/offsets. Derived systems should override the protected virtual methods to react to lifecycle events and must respect the subscription/unsubscription behavior implemented here.
Fields
private LoadGameSystem m_LoadGameSystem
This holds the reference to LoadGameSystem retrieved from the default Entity World (World.DefaultGameObjectInjectionWorld). It's used to register a callback for save-game-loaded events. The field is initialized in OnCreate only when running in the default injection world and cleaned up in OnDestroy.
Properties
- (none)
This class does not expose additional properties. It provides virtual methods for configuration (GetUpdateInterval/GetUpdateOffset) and a ResetDependency helper instead.
Constructors
protected GameSystemBase()
Constructor marked with [Preserve] on the derived OnCreate; basic protected constructor used by the Entities/DOTS system. No initialization logic occurs here — setup is performed in OnCreate.
Methods
protected override void OnCreate()
Called when the system is created. Subscribes to GameManager lifecycle events:- Registers WorldReady, GamePreload, GameLoadingComplete callbacks on GameManager.instance.
- Subscribes to Application.focusChanged.
-
If running in World.DefaultGameObjectInjectionWorld, gets or creates the LoadGameSystem and adds GameLoaded to its onOnSaveGameLoaded delegate. All callbacks are wrapped so exceptions raised in derived handlers are caught and logged (using COSystemBase.baseLog), preventing exceptions from bubbling into the engine.
-
protected override void OnDestroy()
Tears down subscriptions: - Unsubscribes GameManager lifecycle callbacks.
- Removes the GameLoaded delegate from LoadGameSystem if it was added.
- Unsubscribes Application.focusChanged.
-
Calls base.OnDestroy(). This ensures no dangling delegates remain after the system is destroyed.
-
private void FocusChanged(bool hasfocus)
Internal handler for application focus changes. Calls OnFocusChanged(hasfocus) in a try/catch and logs any exception. -
private void GameLoadingComplete(Purpose purpose, GameMode mode)
Internal wrapper invoked by GameManager when loading completes. Calls OnGameLoadingComplete(purpose, mode) inside a try/catch and logs errors; on exception the system is left enabled but an error is reported (consistent with existing logging pattern). -
private void GameLoaded(Context serializationContext)
Internal wrapper invoked when a save-game is loaded (via LoadGameSystem). Calls OnGameLoaded(serializationContext) inside try/catch; on exception it logs and disables the system (base.Enabled = false). -
private void GamePreload(Purpose purpose, GameMode mode)
Internal wrapper for the GameManager preload step. Calls OnGamePreload(purpose, mode) inside try/catch; on exception it logs and disables the system. -
private void WorldReady()
Internal wrapper called when the world is ready. Calls OnWorldReady() in try/catch; on exception it logs and disables the system. -
protected virtual void OnWorldReady()
Virtual hook for derived classes to implement logic when the world is ready. Default implementation is empty. -
protected virtual void OnGamePreload(Purpose purpose, GameMode mode)
Virtual hook called during game preload. Default implementation is empty. -
protected virtual void OnGameLoaded(Context serializationContext)
Virtual hook called when a save-game has been loaded. Default implementation is empty. Exceptions thrown here will be caught by the wrapper and will disable the system. -
protected virtual void OnGameLoadingComplete(Purpose purpose, GameMode mode)
Virtual hook called when game loading is complete. Default implementation is empty. -
protected virtual void OnFocusChanged(bool hasFocus)
Virtual hook for focus change events. Default implementation is empty. Exceptions from user code are caught by FocusChanged wrapper. -
public virtual int GetUpdateInterval(SystemUpdatePhase phase)
Returns the update interval in frames for the given system update phase. Default returns 1. Derived systems can override to control update frequency. -
public virtual int GetUpdateOffset(SystemUpdatePhase phase)
Returns the update offset for a given system update phase. Default returns -1. Derived systems can override to shift the update timing relative to other systems. -
public void ResetDependency()
Resets the system's JobHandle dependency to default (JobHandle.Zero). Use this to clear scheduling/dependency state when needed.
Usage Example
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
// Custom initialization for your system.
// Example: register resources or prepare state that needs GameManager hooks
}
protected override void OnWorldReady()
{
// React to world-ready event
}
protected override void OnGameLoaded(Context serializationContext)
{
// Deserialize or reinitialize state from the save
}
protected override void OnFocusChanged(bool hasFocus)
{
// Pause/resume logic when application focus changes
}
public override int GetUpdateInterval(SystemUpdatePhase phase)
{
// Run every 2 frames for a specific phase if needed
return phase == SystemUpdatePhase.PostPresent ? 2 : base.GetUpdateInterval(phase);
}
Notes and modding tips: - Always call base.OnCreate() and base.OnDestroy() when overriding to preserve subscription behavior. - The class protects the game from exceptions thrown in overrides by catching and logging them; however, critical failures in OnGameLoaded/OnGamePreload/OnWorldReady will disable the system — ensure your overrides handle errors gracefully. - When subscribing additional delegates or registering resources, mirror the cleanup in OnDestroy to avoid leaks or crashes when the system is unloaded.