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).
With this change, a line like the following can be added:
[csharp][assembly: UnityEngine.UnityAPICompatibilityVersion("1.2.3f1")] // in C# and Boo[/csharp]
[js]@assembly: UnityEngine.UnityAPICompatibilityVersion("1.2.3f1") // in UnityScript[/js]
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).
Feel free to ask / comment