IoC Container for Unity3D – part 1

Note: I published the new Svelto.IoC container

Unity is quite a good game development tool, but, although I like most of its features, the code framework is awkward to use on big projects where code maintainability is of fundamental importance.

The considerations in this article do not really apply to simple projects or projects developed by one or two persons. For these specific cases, Unity is good enough. The arguments in this article apply to medium-big projects developed by a medium-big size team.

I will not talk about all the flaws I found, but I will focus on one specifically: inject dependencies inside Unity entities.
A dependency is defined as an object needed by another object to execute its code. If a class A needs the instance of a class B to execute its code, B is a dependency for A. When B is passed into A, we say that B is injected into A.

The problem

Unity is based on the concept of “Entity Framework”. An Entity Framework brings many benefits: pushes the users to favor composition over inheritance, keeps the classes small and clean focusing on single responsibilities, promotes modularity. This is in a perfect world…

In Unity, the Entites are called GameObjects and the Components are based on MonoBehaviour implementations. Personally I have some golden rules I want to follow when I implement MonoBehaviours for GameObjects:

  1. MonoBehaviours should always operate within the GameObjects they are attached to.
  2. MonoBehaviours are reusable, single responsibility classes.
  3. GameObjects should not be created without a view, like a mesh or a colliders or something that is really an entity in the game.
  4. MonoBehaviours can know other components on the same GameObject using GetComponent.
  5. The behaviour of a GameObject should be extended adding MonoBehaviours instead of adding methods to a single MonoBehaviour.

The problem is, as many of you know already, that Unity does not really allow to follow most of these rules because of the way the dependencies must be solved. In fact what happens if my component needs to communicate with other classes? Let’s say there is a Level class and for some reasons this class must know the monsters that are still alive. When a monster dies, how is it possible to communicate the fact to the Level object?

Currently there are 3 simple solutions to this problem:

  1. Level is a Monobehaviour created inside a GameObject that has no view. All the monsters will look for the Level class using the GameObject.Find call inside the Start or Awake functions and inject themselves into the Level.
  2. Level is a Singleton.
  3. Like 1, but Level is found through Object.FindObjectOfType.

albeit, I reckon there are problems in following all the three possible solutions:

What’s wrong with GameObject.Find

The first solution breaks my golden rules, which would be not a big issue since they are actually more guidelines for good design. Instead the real problem is the design of GameObject.Find. GameObject.Find is one of the example of how awkward the Unity Framework is for big project development.

What happens if someone in the team decides to rename the GameObject? Should GameObjects renames or deletions been forbidden ? GameObject.Find can lead to several run-time errors that cannot be caught in compiling time. This scenario could be really hard to manage when dozens and dozens of GameObjects are searched through this function.

What’s wrong with the Singleton

Singleton is a controversial argument since the pattern has been invented. I am personally against the use of Singleton. However if you ask me why I am against the Singleton, I will not answer you with the usual answers (break encapsulation, dependencies hiding, many issues to test the code through unit test, being bound to the implementation of a service instead of its abstraction), but with the hindsight of the practice: your code will become a big pile of crap after a while. This is because the use of Singletons does not involve any design constriction that, while apparently makes the coder life easier, will make it a hell later on, when the design of the classes becomes an incomprehensible blob of code without a structured flow. Projects developed by one of two coders couldn’t shown it at first or ever (for example, if the project doesn’t need to be maintained over time), but mid-size projects will pay the consequences of wild design pretty soon.

What’s wrong with the Object.FindObjectOfType

How should the Level object be injected inside the Monster class then? There is actually a third solution, that is calling the function Object.FindObjectOfType. However, what is FindObjectOfType? Object.FindObjectOfType could be seen as a wrong implementation of the Service Locator Pattern, with the difference that it is not possible to abstract the implementation of the service from its interface. This is another problem of Unity framework, Unity seems to hate the concept of interface. Interface is the most powerful concept at the core of every well designed code. Instead to push the coders to use interfaces, Unity pushes the coder to uses Monobehaviour, even when the use of Monobehaviour is not necessary.

The solution

There are 3 ways to resolve dependencies: using the Service Locator pattern, injecting dependency manually through constructor or setter and using an Inversion Of Control container. I do not like to use the Service Locator Pattern because the SLP itself is a singleton (or a static class) and this could lead to some severe limitations compared to the IoC container solution. However using an IoC container in Unity is not simple because Unity does not specify a place where the application can be initialized.

Explaining what an Inversion of Control container is needs probably another article, so I will be simple with it. An IoC container is a…..container that contains the dependencies that must be injected. It is called IoC because the design is created in such a way that the objects are never created by the user (in fact you can also forget the use of the new keyword), but they are lazily created by the container when they are requested.

There are several IoC containers out there, a lot written in c# as well, but practically no one works in Unity and most of all, they are damn complicated*. For these reasons I decided to create an IoC container for Unity trying to keep it as simple as possible. Actually creating a basic IoC container is pretty straightforward and everybody can do it, my implementation has just a few tweaks that makes it simple to use with Unity projects.

Conclusion (for this article)

The second part of this article (including source code) is now available here:

*Since when I first wrote this article, new IoC containers have been coded. The best ones out there are StrangeIoC and ZenInject. Google them, it’s worth it.

18 thoughts on “IoC Container for Unity3D – part 1

  1. Hey Sebastiano,

    I have to admit I never used an IoC container before, and I would really be curious to see a continuation to this article, to learn more and maybe change my current design patterns.

    As of now, my solution to the problem is to usually keep my [Level] class as one of many “main” MonoBehaviours of an empty “Brain” GameObject, and then go through a global Notificator (which is the only singleton in my project) that every class uses to send events. Then I just listen to [MonsterBornEvent] / [MonsterDieEvent] from the [Level] class.

  2. Nice article. I’m using a type of IoC by myself and I think it solves most of the described problems well.
    The Object.Find method also have the disadvantage that it looks through all gameobjects in a scene, so this is terribly slow and should not be used easily (may as well apply to Transform.GetChild).
    The singleton pattern may be controversal, but it is imho a valid way to bypass some of these problems for smaller projects, though it’s not a fitting solution for larger projects.

    So I’m looking forward to your next chapter of the article :)

  3. I am quite interested to see an IoC container for Unity3d, as I have been looking around to find one that does work with it. Thanks for your efforts, and sharing them (possibly) with others!

  4. I don’t get it why not just use events?

    Also have you tried Ninject? I’m looking to use it for my future Unity3d projects.

    1. I do use events, but events are not suitable to solve all the communication issues. Moreover two instances must know anyway each other to setup the events communication (unless you use singleton event bus, which I loathe). I actually wrote a little post about events and commands (I use commands widely as well). Another technique I like, but I do not use much, is the mediator communication.

  5. +1 Great stuff you mentioned there! Particularly your points about how GameObjects and MonoBehaviours should be implemented. I’ve had lots of issues before with my GameObjects setup. I wasn’t doing that much wrong ‘seemingly’ but now reading this and thinking back, I see why… Thanks for the article!

  6. Fantastic article that made me start using IoC on Unity in a more organized fashion! (Although I always used IoC on systems development, I had not tried to use it with a dedicated container on Unity until reading this.)

    Upon your proof of concept, I ended up creating a fully IoC container (that grew so much that deserved being released!):

    Anyway, thanks for the great couple of articles!

    1. Thanks André..I will soon blog another article, which clarify very important aspects related to IoC principles. Meanwhile I have tweeted your work 😀

Leave a Reply