Skip to content

Instantly share code, notes, and snippets.

@dogfuntom
Last active May 21, 2024 21:29
Show Gist options
  • Save dogfuntom/6aa1e7cb6e9bf3e482b6a6e790e28776 to your computer and use it in GitHub Desktop.
Save dogfuntom/6aa1e7cb6e9bf3e482b6a6e790e28776 to your computer and use it in GitHub Desktop.
Dependency Injection libraries for Unity game engine in 2022

For brevity sake, this gist assumes that you don't need convincing regarding DI in Unity. Still, even without any focus on convincing, it can be beneticial to read a refresher about the topic of purpose and usefullness of DI in Unity.

  1. When DI is not used, Singletons become unavoidable. Singletons are not compatible with unit-tests and reuse, but it's not losing access to them that is important here. When something is not compatible with them, it's a symptom of a bigger illness incoming: rigid architecture that will react poorly to changes (e.g. in game design) and will limit the number of available decisions (e.g. in game design).
  2. When DI is used but not IoC, it's still hard to avoid using having at least one Singleton. One way to avoid it is to use Service Locator but it's an infamous anti-pattern. (While noticable number people still defend Singleton, almost nobody defends Service Locator.)
  3. In traditional C# code it's easy to avoid having a DI container by keeping all dependencies in constructors and initializing everything in Main. In Unity, there are MonoBehaviours that can't be initialized in this fashion. Also, in Unity, there's no Main. Thus, in Unity, implicit DI is not possible, i.e. one has to explicitly use 3rd-party container or write one's own one.

Because of point 2 above, I'll focus on IoC container and mostly ignore pure DI.

IoC containers for Unity game engine

Deprecated libraries

Be careful, multiple famous IoC containers are deprecated. At a first glance, it may seem fine to forgive lack of recent commits. After all, if it's mature, then all the basics are done and polished and bugless. In other words, if it the project would be active, then all the new commits would be just exlusively about advanced features. Right? No. The world of game development doesn't work like that. It must innovate rapidly and fretting about backward compatibility is not compatible with this reality. And lack of fretting about backward compatibility leads to fast library rot. I.e. the next or next after next major version of game engine will be incompatible with it.

Notable deprecated IoC containers: Adic, Zenject¹ (use Extenject instead).

¹ Yes, technically, Zenject is maintained. But after the Zenject controversy there's no point in favoring it over more active Extenject.

Current libraries

IoC container is such a pattern that its implementations become nearly indistinguishable from each other once they mature. Still, you have to choose one and choose wisely. Even a small quirk may become very irritating after years of dealing with it if it's particularly noticable in your project.

  • StrangeIoC:
    • Assists in avoiding MonoBehaviours. In other words, its design assumes that you want to minimize MonoBehaviour usage. (Thus, if your project wants MonoBehaviours, prefer some other IoC container.)
    • Beginner-friendly because of rich documentation and popularity (big community). That is, if you're already skilled enough to be capable of either minimizing usage of MonoBehaviour or of extending your IoC container with richer support of MonoBehaviour.
  • Extenject: Beginner-friendly because of rich documentation and popularity (big community).
  • Microsoft.Extensions.Hosting.Unity:
    • Instead of implementing DI, it uses the new built-in IoC container that comes out of the box with .NET now.
    • If I interpreted its readme correctly, regarding Unity support, only registering MonoBehaviours as dependencies is implemented. I.e. there's no instantiation with injection or scene handling out of the box.
  • VContainer: Intended to be more performance-optimization-friendly than Extenject.
  • Reflex: Intended to be even more performant than VContainer.
  • UniDi: The next thing from the author of Extenject.
  • Impossible Odds: A whole toolkit instead of just a single IoC container. (I don't need to tell you why toolkits are both a blessing and a curse.)

More (I don't know what their quirks are):

Bonus:

  • UIComponents — Framework for Unity's UIToolkit. It has a simple dependency injection that is intended only for UI purposes. This way you can use DI in UI only and continue using classic (non-DI) architecture approach in the rest of codebase.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment