Dependency Injection in Unity using Zenject

September 18, 2020

Intro

When developing software, our big concern is to write a clean, maintainable & testable code. When trying to achieve that, we usually face a lot of problems. One major issue is that a class will be most likely dependent on its dependencies, which is not ideal. We will know why furthermore in this article.

Inversion of Control (IoC)

For every problem, there is at least one solution. For our case, there is the IoC which is a programming principle. As its name tells, it tends to invert the responsibilities. So basically the class will only execute the logic of its dependency without owning its creation which will be controlled from an external generic framework.

To get the big picture, let’s see how the legacy code looks like:

public class PlayerController
{
	private InputsManager _inputsManager;
	
	public PlayerController()
	{
		_inputsManager = new InputManager();
	}
}

This is the real definition of dependency. You can see clearly that the PlayerController script is highly dependent on the InputsManager. Now, imagine that we need to call the inputs manager from a dozen more scripts, this will be a mess…

Now let’s fix it :

public class PlayerController
{
	private IInputsManager _inputsManager;
	
	public PlayerController(IInputsManager inputsManager)
	{
		_inputsManager = inputsManager;
	}
}

With this implementation, the PlayerController will get the InputsManager from a higher class and will not care about its concrete implementation, what matters is that it can call the needed logic.

That’s exactly what Dependency Injection is, an application of the IoC principle. Ideally, all dependencies will be created in a container. Following that, an injector will distribute them when and where needed.

When trying to apply this in Unity, we will face a big problem. Unity relies heavily on using MonoBehavior class that can be attached to a game object in the scene. However, it comes with the downside that we can’t use the constructor on this type of class. So the only way to recognize Monobehavior class dependencies is by looking at its public fields or private serialized fields.

Zenject: “The Saviour”

Zenject is an open-source Dependency Injection framework, lately renamed to Extenject which is a fork from the Zenject repository with bug fixes and more updates. The framework was mainly developed for Unity but it can be used in all other C# projects.

How it works

The framework requires binding all dependencies needed in an Installer (could be split into more than one Installer). Let’s see an example:

public class GameInstaller: MonoInstaller
{
	public override void InstallBindings()
	{
		Container.Bind<IInputsManager>().To<InputsManager>().AsSingle().NonLazy();
		Container.Bind<PlayerController>().AsSingle().Lazy();
	}
}

In the code above, we bind the concrete class to the interface, and any class that takes IInputsManager as input will receive the the same instance of it as well as specifying that the creation should be non-lazy.

public class PlayerController
{
	private IInputsManager _inputsManager;
	
	[Inject]
	public PlayerController(IInputsManager inputsManager)
	{
		_inputsManager = inputsManager;
	}
}

The [Inject] annotation above the constructor call will deal with the injection of the IInputsManager so you don’t need to manage the object creation at all. That’s too good, right?

Since with Monobehaviors we are not allowed to have constructors, we can use Method Injection:

public class PlayerController : MonoBehavior
{
	private IInputsManager _inputsManager;
	
	[Inject]
	public void Construct(IInputsManager inputsManager)
	{
		_inputsManager = inputsManager;
	}
}

Conclusion

This article is just a teaser to help beginners start. The framework is impressively well made so the more you spend time learning and testing things, the more you will know that it’s a must-have framework in every Unity project.

I just scratched the surface in this short tutorial, so the rest will be on you to dig deeper and hone your skills! If you have any questions, feel free to ask me via email.


Are you searching for my Resume?→Click!