Assembly Updater: Faster API usage detection

With the introduction of Unity 5.0 we are taking the opportunity to clean up / improve some APIs, but since, at the same time, we want to make the upgrade process as painless as possible, we’ve been working on automatic API update (as discussed by Lucas in this post) support for both scripts and assemblies used in projects. Basically there are two tools, AssemblyUpdater and ScriptUpdater, which are in charge of applying the actual API updates.

In the case of scripts, the detection of usage of changed API that we can automatically update happens by checking the presence of the a specific string (UnityUpgradable) in compiler error messages so we don’t have any performance impact in this process.

In the case of assemblies, our first approach was to simply scan the assemblies at import time, looking for such changed API references. For most game developers this works well (since usually they don’t keep importing assemblies all day long), but this proved to be a non optimal solution for, at least a group of, Asset Store developers that build assemblies using external tools (VS, Mono, etc) and import them into Unity to test, document, or for some other reason.

In order to support such scenarios, we are introducing a new .Net attribute (UnityAPICompatibilityVersionAttribute) that can be applied to assemblies to declare that they only use APIs that are compatible with a specific Unity version; when the assembly updating tool runs it checks the assembly being processed for this attribute and assumes the assembly does not need to be updated if the version in the attribute matches the current Unity version (Application.unityVersion).

The updater will not bother to check the assembly containing this code when it gets imported into Unity (if Unity has the same version, i.e, 1.2.3f1).

Note that we don’t have the concept of “backward compatibility” which means that if you mark your assembly as compatible with Unity API version X + 1 and import this assembly in Unity version X (of course, assuming both Unity versions have the AssemblyUpdater, i.e, both are >= 5.0), AssemblyUpdater will scan the assembly looking for candidates for updating.

Another benefit of this approach is that assemblies that get automatically updated will get this attribute injected by the updater, so, if for any reason (for instance, the user chooses to “Reimport all” assets) the assembly is imported again, the updater will take the attribute into account.

Please, keep in mind that even though this is how it is implemented right now, we have considered other alternatives (for instance, start versioning UnityEngine assembly) and that if we decide to go with one of these alternatives we may change the way the updater decides whether to search for obsolete APIs being used (we could check the version of the UnityEngine.dll being referenced to decide if we version UnityEngine).

This attribute is only an optimization to allow AS authors to tell the updater that his/her package has no obsolete API usage; this way the updater can completely skip such assemblies and so does not add extra time to the AS author workflow.

@emil. We’ve had some (basic) discussion about this but nothing official. I think the code is modular enough to support (with some small changes) AS devs (from the top of my head, the major missing part, is a way to allow “custom” configurations” to be specified).

Often scripts and online resources will be using older versions of the APIs.

Could we see version selection options in the online unity documentation similar to the msdn which allows you to select which version of the relevant assembly {.NET, Visual Studio or Office} you want to view the documentation of?

I like that. Why go through all of that which you explained in this post when you can just bundle 3-5 UnityEngine assemblies for developers to use when, say, they REALLY need to update during the development cycle (which in itself is usually considered a bad idea).

Am I missing something here?

I can’t imagine WHAT it will take to maintain UnityAPICompatibilityVersionAttribute and all updaters/injectors/compatibility checkers e.t.c. with each major (or even minor?..) Unity update.
Is this really rational?