Skip to main content

Class UnityServiceLocator

A service locator that provides runtime access to globally shared IUnityGameService instances without requiring direct references between systems.

public class UnityServiceLocator

Inheritance​

Examples​

// Bootstrap — call once at application startup (e.g. from Bootstrapper.Awake):
UnityServiceLocator.Initialize();
UnityServiceLocator.Current.Register(new UnityEventAggregator());

// Later, anywhere that needs the event aggregator:
if (UnityServiceLocator.Current.TryGet(out var aggregator))
{
aggregator.Publish(new PlayerMovedMessage(transform.position));
}

// Service components self-register in Awake and unregister in OnDestroy:
private void Awake() => UnityServiceLocator.Current.TryRegister(this);
private void OnDestroy() => UnityServiceLocator.Current.TryUnregister(this);

Remarks​

The locator is initialised by the bootstrapper before any scene Start call runs, so services are always available when game objects need them. The single Current instance is intentionally created via Initialize rather than a static field initialiser so that tests can call Initialize to reset state between runs.

Properties​

Current​

Gets the active global service locator instance.

public static UnityServiceLocator Current { get; }

Property Value​

UnityServiceLocator

Methods​

ForceRegister<T>(T)​

Registers the service of type T, overwriting any existing registration for that type without logging an error.

public void ForceRegister<T>(T service) where T : IUnityGameService

Parameters​

NameTypeDescription
serviceTThe service instance.

Type Parameters​

NameTypeDescription
TThe type of the service.

Remarks​

Use in testing (to inject a mock) or during hot-reload scenarios where intentional replacement is expected. In production bootstrapper code prefer Register` so accidental double-registration is caught early.

ForceUnregister<T>()​

Removes the registration for type T unconditionally, regardless of which instance is currently registered.

public void ForceUnregister<T>() where T : IUnityGameService

Type Parameters​

NameTypeDescription
TThe type of the service.

Remarks​

The escape hatch for teardown scenarios where the registered instance may have already been replaced or is unknown — for example, when a test fixture tears down the service locator state without knowing which concrete implementation was registered.

Get<T>()​

Returns the registered service of type T, throwing if it is not found.

public T Get<T>() where T : IUnityGameService

Returns​

T — The registered service instance.

Type Parameters​

NameTypeDescription
TThe type of service to retrieve.

Remarks​

Use this overload when the service is guaranteed to be present by the time the caller runs (i.e., registered before any scene Start). An exception here signals a programming error in the bootstrapper — the service should have been registered and wasn't. Prefer TryGet` in any code path where the service is optional or the registration order is uncertain.

Exceptions​

InvalidOperationException — Thrown when T is not registered.

Initialize()​

Creates the global service locator instance if one does not already exist.

public static void Initialize()

Remarks​

The null-coalescing assignment (??=) makes this call idempotent — calling it more than once (e.g. across domain reloads in the editor) leaves the existing instance and its registered services untouched rather than wiping them.

Register<T>(T)​

Registers the service of type T, asserting that no prior registration exists for that type.

public void Register<T>(T service) where T : IUnityGameService

Parameters​

NameTypeDescription
serviceTThe service instance.

Type Parameters​

NameTypeDescription
TThe type of the service.

Remarks​

Use this during bootstrapper setup where double-registration would be a programming error. If the type is already registered, an error is logged and then Dictionary.Add throws ArgumentException — the intent is to surface the mistake loudly rather than silently overwrite an existing service. For intentional replacement, use ForceRegister` instead.

Exceptions​

ArgumentException — Thrown by Dictionary.Add when T is already registered.

TryGet<T>(out T)​

Attempts to retrieve the service of type T without throwing.

public bool TryGet<T>(out T GameService) where T : IUnityGameService

Parameters​

NameTypeDescription
GameServiceTThe retrieved service, or default if not found.

Returns​

bool — true if the service was found; otherwise, false.

Type Parameters​

NameTypeDescription
TThe type of service to retrieve.

Remarks​

The safe counterpart to Get`. Use when the service might legitimately be absent — for example, when a feature is optional or when calling from a component that can run before the bootstrapper has finished registering all services. A warning is logged on miss so that missing registrations remain visible in the console.

TryRegister<T>(T)​

Registers the service of type T only if nothing is already registered for that type.

public bool TryRegister<T>(T service) where T : IUnityGameService

Parameters​

NameTypeDescription
serviceTThe service instance to register.

Returns​

bool — true if the service was registered; false if one was already present.

Type Parameters​

NameTypeDescription
TThe type of the service.

Remarks​

Designed for MonoBehaviour services that self-register in Awake. In Unity, Awake can fire multiple times across scene loads (domain-reload-off mode, additive scenes), so using [Register](UnityServiceLocator.mdx) in Awakewould log spurious errors on subsequent loads.TryRegister` is safe to call repeatedly — it silently no-ops when a registration already exists.

TryUnregister<T>(T)​

Removes the registration for type T only if the registered instance matches service.

public bool TryUnregister<T>(T service) where T : IUnityGameService

Parameters​

NameTypeDescription
serviceTThe specific service instance to remove.

Returns​

bool — true if the service was removed; false if not registered or if the registered instance does not match.

Type Parameters​

NameTypeDescription
TThe type of the service.

Remarks​

The instance comparison prevents one system from accidentally unregistering a service that was replaced by another system — for example, if a new scene registered a fresh instance under the same type, an old teardown callback will fail rather than silently removing the replacement. Use ForceUnregister` when you need to remove regardless of which instance is currently registered.

Unregister<T>(T)​

Removes the registration for type T, logging an error if the service is not found or if the registered instance does not match service.

public void Unregister<T>(T service) where T : IUnityGameService

Parameters​

NameTypeDescription
serviceTThe specific service instance to remove.

Type Parameters​

NameTypeDescription
TThe type of the service.

Remarks​

Mirrors TryUnregister` but treats a failed removal as an error rather than a recoverable condition. Use in places where the service is guaranteed to have been registered by this caller and its absence would indicate a lifecycle bug.

  • Examples
  • Remarks
  • Properties
    • Current
  • Methods
    • ForceRegister<T>(T)
    • ForceUnregister<T>()
    • Get<T>()
    • Initialize()
    • Register<T>(T)
    • TryGet<T>(out T)
    • TryRegister<T>(T)
    • TryUnregister<T>(T)
    • Unregister<T>(T)