ETSystemRegistry
The toolkit implements the service locator pattern in its framework, using concrete MonoBehaviours instead of service interfaces.
This is done to prevent the over-reliance on singletons, which as a toolkit with many manager/controller components, it can be an issue. ETSystemRegistry acts as the single point of access when trying to reference a manager or controller.
The ETSystemRegistry component is attached to the ExplorationToolkitManager GameObject, which must be present in all scenes you wish to implement the toolkit's systems.
If you've dug through the code, you've likely seen lines such as this:
ETSystemRegistry.Instance.Get<UIManager>();
This returns a reference to the UI Manager that's currently in the scene.
What is a system?
The term system in the ETSystemRegistry encapsulates management components such as the UIManager and InputManager, as well as player-centric controllers such as the InspectController and PickupController.
For all the management and controller systems you wish to implement, make their GameObjects a child of the ExplorationToolkitManager, as this is how they will be identified and automatically registered upon initialization.

Where are these systems?
- Management Systems -
Core > Prefabs > Systems > Managementfolder. - Controller Systems -
Core > Prefabs > Systems > Controllersfolder.
Working with the ETSystemRegistry
If you are looking to add your own code to the toolkit or implement your own custom management scripts, I recommend integrating it within the current system. This will make your systems accessable without the need for its own direct dependancy or singleton.
Creating a new system
In this example, let's say we've created a ScoreManager component.
-
Have the class implement the
IRegisterableSysteminterface. The ETSystemRegistry will automatically find and register this system, if the component's GameObject is a child of it.public class ScoreManager : MonoBehaviour, IRegisterableSystem { }
Manually registering a system
Creating a system via the way mentioned above works for systems that are initialized at runtime. Generally, this is the recommended method, but if you wish to spawn a system later on in the game, you can register/unregister a system like so. Do note, these classes don't require the IRegisterableSystem interface.
-
In the
OnEnablefunction, register the system with ETSystemRegistry.void OnEnable () { ETSystemRegistry.Instance.Register(this); } -
In the
OnDisablefunction, unregister the system. This helps to prevent any errors later on if the component gets destroyed.void OnDisable () { ETSystemRegistry.Instance.Unregister(this); } -
Now the ScoreManager can be accessed from anywhere with the following:
ETSystemRegistry.Instance.Get<ScoreManager>();
Why isn't this the default way?
Registering a system manually can give you more precision over what and when a system is setup, but many components require subscribing to system events upon initialization. This can cause order of execution issues, so having every system registered via the IRegisterableSystem interface at runtime by the ETSystemRegistry, solves this problem.
Referencing a system
Convention in the toolkit is to not reference the system registry directly when needed, but rather create a read-only property in the script where it will be needed.
private InputManager inputManager => ETSystemRegistry.Instance.Get<InputManager>();
private UIManager uiManager => ETSystemRegistry.Instance.Get<UIManager>();
This allows you to write cleaner looking code, going from something like this:
ETSystemRegistry.Instance.Get<UIManager>().CloseCurrentWindow();
To this:
uiManager.CloseCurrentWindow();