One Strange Week in Spain

will_aurimas_marc

Let’s start with what this article will not be about. Dependency injection will not be a native feature in Unity. Not, at least, for the foreseeable future.

But for one exciting week, it was.

A question I got more than once when I joined Unity was “will Strange become a part of Unity?” I answered, “No, Unity are hiring me. Not buying Strange.” Nevertheless, the idea of integrating certain features of Strange  directly into Unity has never been far from my mind.

Last week, Unity engineers from all over the world met up in Malaga, Spain for a big hackweek: one hundred and fifty engineers, all brainstorming and blue-skying projects they thought might be fun or useful for the company and/or community.  And a mighty assembly of ideas it was.

Among these brave souls, our friend Will Corwin proposed the integration of dependency injection directly into Unity as a native feature. Obviously, this was something I couldn’t pass up. Together with colleague Aurimas Cernius, we leapt in and made it so.

Our goals:

  • Create a simple, easy-to-use DI system
  • Explain the value of DI to hackweek participants

We were not attempting to make Strange a native feature. The MVC construct on which Strange is based is a useful application paradigm, but it’s certainly not the only one. None of us thought that the larger framework was appropriate as a native feature. What we did (and do) regard as appropriate, was the injection feature itself. To do this we needed the following pieces:

  • The injection system, obviously
  • The reflection system, for efficient caching
  • A context, for writing bindings

We started by copying the appropriate packages from Strange, stripping out anything that wasn’t useful to our case. Mostly this meant simplifying the Context.

One of the cool things about adding injection directly to Unity is the ability to ditch some of the shoehorned functionality Strange copes with on startup. UnityEngine.Injection, as our system came to be, had C++ hooks to kick off certain processes, making those early milliseconds cleaner and more reliable.

It all started with this player setting.

Use_DI

With this Boolean switched on, the DI system went to work, searching for a Context marked with the [BindingContext] attribute. This meant that a ContextView in our system was optional. Sure, you’d want one to mark out sub-contexts, but a viewless Context is probably a better choice for your first Context, which shouldn’t have to be tied to a view in any way, and shouldn’t be destroyed if your scene changes (we’ve even thought of implementing this idea in Strange itself).

Of course we have our familiar [Inject] and [PostConstruct] tags. The only other place where our injection system touches the developer is in MonoBehaviours. Aurimas wrote this native hook:

[InjectDependencies]
public class SomeClass : MonoBehaviour {
    [Inject]
    public ISomeService YouKnowTheDrill { get; set; }
}

Any MonoBehaviour so marked seeks out and finds the correct Context, based on the same set of rules Strange uses. The results of these simple changes were pretty cool.

  • A developer can start playing with DI with as little as a button click and about 5 lines of code (An Inject tag and a simple Context). Compare that with what it currently takes to get into Strange for the first time.
  • MonoBehaviours can request injection directly. They don’t need to extend View.
  • Strange (or other IoC systems) could be layered on top of this system.
  • A colleague pointed out that resolving bindings should really be a compile-time operation, not runtime. We agree. That could potentially be fixed by internalizing DI.

We had most of the functionality working by Wednesday morning, so we had accomplished our first goal. But for the second goal — explaining the value — we didn’t yet feel like we had an ideal presentation. Fortunately, inspiration struck late Wednesday: we quickly re-tooled a one player game to two player and wired it up with a real-time server.

Actually, we used not one real time server but two! We leveraged an experimental server written by another hackweek team, then showed how using DI bindings we could instantly swap between the experimental one and UNet.

The video below (no audio) shows our presentation “slides” along with some side-by-side video of the game running with the experimental server.

[BindingContext]
public class MyGameContext : Context
{
  protected override void mapBindings()
  {
    InjectionBinder.Bind<GameManager>().ToSingleton();
    InjectionBinder.Bind<IPlayer>().To<PlayerModel>().ToSingleton();
    InjectionBinder.Bind<IDispatcher>().To<Dispatcher>().ToSingleton();
    //InjectionBinder.Bind<IRealtimeServer>().To<NullServer>().ToSingleton();
    InjectionBinder.Bind<IRealtimeServer>().To<UnetServer>().ToSingleton();
    //InjectionBinder.Bind<IRealtimeServer>().To<CloudCodeServer>().ToSingleton();
  }

  protected override void postBindings ()
  {
    InjectionBinder.GetInstance<GameManager>();
  }
}

This was a fun project. It led us to consider more deeply than we ever had before what it would mean to integrate DI directly into Unity. As I said at the top, this isn’t something we see being implemented in real product anytime soon, but we made more folks within Unity aware of what we do and why. We met some great people, heard about some amazing ideas, and started some conversations that may someday bear fruit.

Advertisements

Babel Naming

Journey From BabelThis just tickled my funny bone, and I thought I’d share. As I’m working on the documentation for the next version of Strange, I thought I’d go through some of my early notes, looking for ideas. And I stumbled across this blast from the past.

The development codename for what eventually became Strange was Babel. As the framework was nearing completion — and we knew we were going to open-source it — we decided we needed a cool name to get it noticed, so we threw together a brainstorming document. Submitted for your amusement, here are all the Stranges that could-have-been…


Babel is the working title for the framework I’ve been building. We’re looking for a name. Feel free to add ideas.

Things to consider

  1. At its heart, Babel is not an injection library. It’s a binding framework. The most important thing Babel does is bind something to something else. One (very important) application of that binding is dependency injection.
  2. Consideration #1 might not matter.
  3. It might be nice to use our initials, TM, to reflect back upon us.*
  4. Consideration #3 might be unnecessary.
  5. Babel is lightweight and modular, something that appeals to developers.
  6. Babel is written for C# and Unity, and will be (so far as we know) the first “serious” attempt to provide a Inversion-of-Control/Dependency Injection framework for this purpose.
  7. If you care, you can see the names of some IoC/DI libraries here.

Name ideas (feel free to add)

  • TieFighter
  • TinMan
  • ThinMan
  • TinType
  • Babel
  • Babylon
  • Unification
  • UncleBob (a reference to the guy who devised the Dependency Inversion Principle)
  • Stingray
    • Ampule
  • IssacNewtonsBinding or the bindingofIssac
    • FirstMotion
    • Newton
  • Boson – “the ‘glue’ that holds matter together”
    • Higgs
    • DarkMatter
  • Fondant (UK: /ˈfɒndənt/, US: /ˈfɑndənt/ or /ˈfɑndɑnt/, from the French: /fɔ̃.dɑ̃/) is one of several kinds of icing-like substances used to decorate or sculpt pastries.
  • Agar or agar-agar is a gelatinous substance derived by boiling[1] a polysaccharide in red algae, where it accumulates in the cell walls of agarophyte and serves as the primary structural support for the algae’s cell walls
  • A carboy (or demijohn) is a rigid container with a typical capacity of 20 to 60 L (5 to 15 gallons).[1] Carboys are primarily used for transporting fluids, often water or chemicals.[2] (as cider maker, I just find these to be funny words)
  • Strange – A strange attractor generates predictable patterns, often in the scope of a chaotic system.
  • Gloo
    • Glue
    • BluTac (thinking of the virtue of sticking things together, but not permanently)
    • Paste / LibraryPaste / PasteLibrary / PasteBoard
    • Duct tape
  • Vulcan MindMeld
    • My mind to your mind
    • Sneaky sci-fi references
      • Liberator
      • SonicScrewdriver
      • Tanstaafl – see here, particularly in relation to Newton’s Second Law of Thermodynamics
      • Klaatu
      • Illudium
      • Tholian (web)
      • Federation
  • Octopus
    • Tentacles
    • TentacleMotion

* The “Us” in this context was ThirdMotion, the company responsible for me bringing Strange to you.

It’s Big, It’s Strange, and I’m Rewriting It

[EDIT]First draft of Introduction is now open for comment[/EDIT]
[EDIT2]The revised architecture diagram is now open for comment[/EDIT2]

Gentlemen, you can't fight in here! This is the War Room!

The Big, Strange How-To has been the standard (and, er, only) textbook on Strange since its inception. But with the exception of a handful of corrections and the addition of a couple of new features, it has remained largely unchanged since it was first written way back alongside v0.5. With the upcoming release of v1.0, I reckon that it’s high time for a proper update.

With the benefit of hindsight and whisky, I’m looking at everything in the BSHT to see what needs updating, adding, or even removing. And that’s where you come in, my friends!

What could we explain better? What has frustrated you most, especially when you were first learning? I especially want to concentrate on the new user: what can we do to flatten the steepness of our learning curve?

Here are my ideas so far. Please leave comments below and I’ll keep this post updated with your input.

Things to add to the Big Strange How To

Re-work the Introduction

New section: opening Strange for the first time (walk-through)

  • Explain the broad structure of the repo.
  • Walk-through of MyFirstProject project
  • Walk-through of MultipleContexts project

Updated section: Signals

  • Beef up the Signals section.
  • Add explanation for the (new to v1.0) ListensTo feature.
  • Change all examples (across all of BSHT) from EventDispatcher to Signals.

Updated section: Mapping across Contexts

This section is really thin. Let’s clarify the concept and the execution. Particularly, explain the reasoning behind multiple Contexts, along with practical info on how to structure them.

Updated section: Reflection

I don’t want to confuse a new user with too much about this…but then the understanding the principles is important.

New section: Pools

Explain how the Pools extension works

New section: Promises

Explain the (new to v1.0) Promises package

New section: Implicit Bindings

Explain the ImplicitBind package

New section: runtime bindings

Explain the (new to v1.0) feature runtime bindings

New mini-section: Strange for extending Unity

A mini-section because it will essentially just link to a separate document specifically about using the (new to v1.0) Editor extension. The current plan is for the Editor extension to live outside the main Strange repo as an optional plug-in.

New section: Testing tutorial

Explain how to run unit tests and write your own.

Enumerate Exceptions for each package

In each package, list and explain each of the thrown errors. In an appendix at the end of the document, put all Exceptions in one place for easy reference.

Replace artwork

All that pesky text art (—–>). Let’s grow up and use PNGs or SVGs or something.

Tutorial

Lots of people asking for something more like a step-by-step tutorial. Particularly questions about uGUI. Should this be here or a separate document?

New Section: Platform Specific Issues

A request in the comments to explain iOS trampolines. Compile a set of other platform-specific gotchas?

New Section: Best Practices

Some cohesive section on Dos/Don’ts when using Strange.

Errata

Add named injection for constructors

How this will work

I’ll going to create the new BSHT as a Google Doc at first. I’ll edit this post and provide a link so everyone can weigh in. In the meantime, feel free to leave comments and ideas.