Skip to content

alexnaraghi/UnityServiceLocator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Unity Service Locator

A typical Unity game needs global access to some objects with full control over instantiation time (NO singletons, NO lazy instantiation), and readable, lightweight code without "enterprise" bloat (NO dependency injection). We're talking under 200 lines of code.

In addition, this package supports unit testing, interfaces, and scoped containers.

I have been using this pattern in Unity with minimal changes for more than 7 years, in multiple small to medium-sized codebases (400k+ lines, 1-10 developers). It's stupid simple to understand and works great for teams.


Get Started

Provided are the 3 core classes (Services, ServiceLocator, and ServiceInstaller), and some examples. The most common usage is global access through Services.

Add a service

Services.Add<YourMonoBehaviour>();
Services.Add<YourPureC#Class>();
Services.AddExisting(someObject);

Add a service by interface

Services.Add<IYourInterface, YourConcreteType>();

Access a service

Services.Get<YourMonoBehaviour>();
Services.Get<IYourInterface>();

Remove a service

Services.Remove<YourMonoBehaviour>();

See the included examples for common access patterns.

MonoBehaviours

The default service locator creates a GameObject with DontDestroyOnLoad and any new MonoBehaviour service will be added to that game object. Your services will exist across scenes unless you choose to remove them.

For scene-specific services, the ServiceInstaller will automatically add and remove MonoBehaviours set via inspector.

Pure C#

The Service Locator can bind any type. Pure C# objects simply won't show up in the inspector, but in many cases they are preferable. You access pure C# objects in exactly the same way as MonoBehaviours, with 'Services.Get()'.

Installer

Every game I've ever worked on has services that depend on each other and need to be instantiated in a well-defined order. That is why I recommend creating and adding services in an installer/bootstrap class at startup and/or in scenes.

The ServiceInstaller will do exactly this for MonoBehaviours, but you can inherit from it or write your own for complete control over how things are instantiated.

Avoid lazy instantiation, it doesn't work for games because it creates lag spikes and dependency bugs. Create and register services in as few places as possible to make dependencies clear.

Flexibility

A service locator is NOT a game engine pattern, it does not define how you make a game and you can use it for as much or as little as you want.

You can add a ServiceLocator into a mature project and simply use it to globally access 3rd party APIs, or you could use it to access game APIs like a camera system. Add interfaces for unit tests or cross-platform code.

For example, the static Services class is provided for global access, but if you wanted multiple service locators or another pattern, simply create a service locator yourself and provide your own form of access.

var serviceLocator = new GameObject().AddComponent<ServiceLocator>();

At the end of the day, it's just a Dictionary of (Type -> object) with some utility methods.

Examples

Included is an Examples folder that illustrates how to add and access services.

ExampleServiceInstaller shows how to add new services in several different ways. GameUI shows how to access services from anywhere.

These examples don't demonstrate game principles, just how to use a service locator.

Pull Requests

Feel free to contribute or provide feedback if you feel anything is missing.

About

General purpose, fast, concise implementation of a service locator for Unity.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages