Singletons... but better
This package provides a way to bootstrap and manage global game systems like saving or music.
It allows for nice and centralized place to define and get systems as opposed to normal messy singleton spaghetti.
To install the package, open Unity Package Manager
Then select "Add package from git URL..."
Then type https://github.com/Wokarol/GameSystemsLocator.git#main
as the URL
If you want to target a specific version, suffix the URL with
#version
, for examplehttps://github.com/Wokarol/GameSystemsLocator.git#v0.2.0
First, you have to create a config class.
This class has to implement ISystemConfiguration
interface and cannot be static.
If you want to disable the boostrapper, you can use
GAME_SYSTEMS_DISABLE_BOOTSTRAPPER
compiler directive.
Keep in mind that you will have to initialize the locator yourself!
This interface defines a single method, void Configure(GameSystems.ConfigurationBuilder builder)
which uses the builder passed as an argument to configure the locator.
Example of such class might look like so:
public class GameConfig : ISystemConfiguration
{
public void Configure(ServiceLocatorBuilder builder)
{
builder.PrefabPath = "Systems";
builder.Add<IMusicSource>(nullObject: new NullMusicSource());
builder.Add<SaveSystem>(required: true);
builder.Add<PlayerHandle>();
}
}
If the PrefabPath
is set, bootstrapper will spawn it and initialize the Locator with the systems present on the prefab. Prefab is loaded before scene is loaded.
For test scenes, you can add
SkipSystemsPrefab
to the name to not load the systems prefab. Locator will still be configured.
(when using additive scenes, all loaded scenes need that keyword otherwise systems prefab is spawned)
.Add<T>(...)
is used to add a game system container to the locator. Optionally it can define if the system is required
or if it has a nullObject
instance.
For more information, refer to in-code documentation
Locator configured like so can then be used to obtain references to game system using GameSystems.Get<IMusicSource>().Play()
at any point in code
This method will get the current system even including the overrides, if no instance is present, it will attempt to return the null object.
Game Systems can be overwritten, for that attach SystemOverrider
component to the game object with game systems that should be used as children. Like shown on the example:
No additional configuration is needed
You can also pass the systems in a list directly, this will call
GetComponent
on them to retrieve a system.
Currently enabling an overrider with
Grab Systems From Children
enabled loops over all systems callingGetComponentInChildren
which might cause a performance hit but I did not yet test it well enough to confirm that or deny
Yes, Service Locator is in GameSystemLocator.Core
namespace
Yes, you can do so by changing the PrefabPath property in Config like
if (/* is debug */)
builder.PrefabPath = "Systems-Debug";
else
builder.PrefabPath = "Systems";
You can use Prefab Overrides to make this process nicer
Currently, getting the system inEnable()
at the beginning of the application lifetime (when entering game mode for example) will almost always lead to an exception. Considering usingStart()
or calling the method right before the system is needed
(Needs further investigation after v0.7.0)
- Fix: Systems prefab being removed after creation
- Add: Non-static Service Locator class
- Change: Complete overhaul of the code architecture
- Add: Option to disable bootstrapper
- Add: Option to not spawn systems prefab
- Add: SkipSystemsPrefab keyword
- Change: Game Systems API
- Fix: Bootstrapper loads after the scene is loaded
- Add: Systems list in System Overrider
- Fix: Having System Overrider enabled while the playmode is entered does not register systems properly
- Add: Readme content
- Add: Code documentation
- Add: System Overrider
- Fix: Created system has "(Clone)" suffix
- Fix: Failure to instantiate a prefab leaves empty object in the hierarchy
- Rename:
AddSingleton
toAdd