Why Consider Using Autofac With Unity3D?
I think using a dependency injection framework is really valuable when you’re building a complex application, and in my opinion, a game built in Unity is a great example of this. Using Autofac with Unity3D doesn’t need to be a special case. I wrote a primer for using Autofac, and in it I discuss reasons why it’s valuable and some of the reasons you’d consider switching to using a dependency container framework. Now it doesn’t need to be Autofac, but I love the API and the usability, so that’s my weapon of choice.
Building a game can result in many complex systems working together. Not only that, if you intend to build many games it’s a great opportunity to refactor code into different libraries for re-usability. If we’re practicing writing good code using constructor dependency passing with interfaces, then things really start to line up in favour of using a dependency injection framework.
Getting Set Up
At the end of my autofac primer article, I provided a link to the Nuget package for Autofac. You’ll notice that there’s a version dependency for .NET 4.5, so if you’re not sure how to get Unity3D working with .NET 4.5, you’ll want to check this other article of mine. It’s very simple, so don’t worry!
Unity3D, at the time of writing this and using version 2018.1.1f1, there’s no native Nuget package support. I haven’t spent too much time investigating alternatives, but not to worry. I’ll explain a quick work around. The TL;DR is that we need the binaries from the Nuget package to be loaded up by Unity3D and we’ll miss out on the Nuget-y-ness for now. Not a huge deal since we’ll still have Autofac support!
- Start a new Visual Studio C# project
- Ensure that the .NET framework is at least 4.5 and more specifically, the version of .NET that you’d like to use in your Unity3D project
- Open up the Nuget package manager in Visual Studio
- Search for Autofac online in the package manager (it should be the same one I referred to above!)
- Add this package to your visual studio project
- Compile this visual studio project
- Assuming you built in debug, go to the output folder (which is in bindebug if you didn’t change anything from default)
- In the output folder, you’ll find “Autofac.dll”
- You’ll want to add this into your Unity3D project’s “Assets” folder
- I like nice folder hierarchies, so I’d suggest making a subfolder inside of “Assets” called “Third Party” or “Dependencies”… Something that’s obvious for what it means
- Drop in the Autofac.dll file into there
- Unity3D will add a corresponding *.meta file to go along with this
Great! We’re almost there. If you want to test it out, open up a script from Unity3D. This will launch a new Visual Studio instance if you haven’t opened up one for your Unity project yet. At the very top of your file you should be able to type:
using Autofac;
And the namespace should resolve! If not, sometimes this takes Unity3D a refresh operation to regenerate the project file on disc, so if you switch to Unity3D again and it starts doing some processing, switching back to Visual Studio might resolve this.
Using Autofac With Unity3D
Up until this point, we’ve proven we can reference Autofac. I’m not going to explain all the ins and outs for how you’ll want to organize your Autofac initialization in this post, but we can walk through a quick example!
- Pick a game object on your scene
- Add a new C# script to it
- Call it whatever you’d like, but make sure you know how to open it
- … now go open it in Visual Studio 🙂
- We should have a method in there called Start()
- If not, feel free to add it:
private void Start() { // TODO: we'll add stuff here }
- Let’s use this code to make a new class that you can put inside the same script file for now:
public sealed class MyAutofacObject { public MyAutofacObject() { Debug.Log("Constructor for our object!"); } public void DoThing() { Debug.Log("Test!"); } }
- Inside this start method, let’s try doing something VERY simple to prove Autofac works!
var containerBuilder = new Autofac.ContainerBuilder(); containerBuilder.RegisterType<MyAutofacObject>().SingleInstance(); var container = containerBuilder.Build() var instance = container.Resolve<MyAutofacObject>(); instance.DoThing();
Now if we run our game, here’s what should happen:
- The script attached to the game object should run
- The Start() method on the script should be the first thing that goes
- The code we added should:
- Make a new ContainerBuilder
- Register our MyAutofacObject type as a single instance
- Build the container
- Resolve an instance of our type
- Log out a message saying it’s in the constructor
- Log out a message that says Test!
And voila! It’s simple, but it should demonstrate that Autofac is working!
Next Steps
This is a very contrived example of using Autofac with Unity3D. It proves that the code can be run, but it doesn’t do too much that’s useful. There are going to be many considerations you’ll need to make for how you want to organize your dependencies, register your classes/interfaces, and so on.
I’ll continue to add into this Unity3D series of posts, but let me know what else you’d like to know about using Autofac with Unity3D! I’d be happy to try and answer, or even create an article to help explain.
Thanks!
Have you been thinking how to structure registration and resolving in MonoBehaviours? Initially I thought about registering in Awake method and resolve in Start or later. Another option would be to register in static constructors, which would allow to resolve anywhere.
Hey Dawid, sorry for the late response! I’ve generally stuck to using the Start() method, and to be fair, I haven’t considered too many other built-in methods just because I haven’t taken the time to really understand the lifecycle for MonoBehaviours. I usually avoid static stuff as much as possible just because I find when I want to unit test stuff, it can cause some issues for how I like to design my tests.
I’ve used this pattern I called “stitching” (And wrote an article here https://www.devleader.ca/2018/06/08/stitching-a-design-pattern-for-unity3d-and-autofac/). This lets me register a “Stitching” class through autofac that can magically get in all the dependencies a MonoBehaviour would probably want in a constructor (but… obviously we can’t pass them into the constructor), and then mostly acts like a factory to set the properties on the MonoBehaviour instance that it creates.
For me this has worked best for how I like to architect my stuff, and while it’s a bit of extra overhead to make a Stitcher class, I find it keeps things nice and separated into their single responsibilities. I get to use autofac magic and MonoBehaviours get created how Unity wants them to 🙂