Using NuGet in Visual Studio Tools for Unity

May 23rd 2015 NuGet Unity Visual Studio

NuGet Incompatibility

Visual Studio Tools for Unity enable the convenience of developing Unity scripts inside Visual Studio. This makes it easy for experienced .NET developers to become tempted to use all of the Visual Studio features available to them. NuGet package manager is one such feature, simplifying the referencing of third party libraries in own projects. A naive attempt to install a random NuGet package into the UnityVS project will most likely fail with an error similar to the following one:

Could not install package 'LightMessageBus 1.0.0'. You are trying to install this package into a project that targets '.NETFramework,Version=v3.5,Profile=Unity Web v3.5', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.

Compliant NuGet Packages

To understand the issue, it's important to know that Unity builds on the Mono framework and doesn't really use .NET framework. To take this into account, the project in Visual Studio has a custom target framework set, which ensures that the right .NET framework subset is in use to make it compatible with Unity.

Target frameworks in Visual Studio Tools for Unity projects

This is quite a problem for NuGet which requires that the package being installed provides the assemblies for the projects target framework. Since it doesn't know anything about Unity's profiles, it requires the package to either provide an exact match with the target framework, or to contain fallback assemblies without a specified target framework. It's unlikely that you'll find many NuGet packages of the former type, so your only option will be packages of the latter type, which is not a recommended practice in the latest versions of NuGet.

If you're the package owner, you can create a suitable package of your own, based on NuGet's conventions for naming target frameworks. In the case of the above error the correct target framework would be net35-Unity Web v3.5. In general it must be named as {framework name}-{profile} where {target framework} will always be net35 for .NET Framework 3.5 and {profile} will be one of the following based on the selected target framework in the project:

Target framework profile
Unity 3.5 .net full Base Class Libraries Unity Full v3.5
Unity 3.5 .net Subset Base Class Libraries Unity Subset v3.5
Unity 3.5 Micro Base Class Libraries Unity Micro v3.5
Unity 3.5 Web Base Class Libraries Unity Web v3.5

Reference Assemblies in Unity

Once you manage to install the package and hence reference the assembly, the project should successfully compile in Visual Studio. Unity will still complain that it doesn't know anything about the types and namespaces from your dependencies:

Assets/Scripts/Coin.cs(3,7): error CS0246: The type or namespace name `LightMessageBus' could not be found. Are you missing a using directive or an assembly reference?

To fix that, you'll need to include the referenced assemblies in your Unity project assets. As with other items, it's not important how you organize them. I suggest, you create a dedicated folder (e.g. Assemblies) and place all the references there to keep them organized. Just drag and drop them from the file system into your project folder:

Drag referenced assembly into Unity

Assembly placed in Unity project folder

Be aware that this creates a copy of the assembly, therefore you'll need to update it manually if you update the NuGet package with a newer version. Also make sure that you include any third party assemblies indirectly referenced by the assembly you're referencing directly from you project, or Unity will complain that it cannot load them:

Unhandled Exception: System.Reflection.ReflectionTypeLoadException: The classes in the module cannot be loaded.

Mono Compatible Assemblies

That's still not the end of all problems, though. As indicated by the target framework, any assemblies used in Unity should be .NET 3.5 compatible, which automatically excludes any of the portable class library profiles. To make matters worse, there doesn't seem to be any information available on the exact version of the Mono framework being used in Unity 5 or its API compatibility.

Previous version was supposedly based of Mono 2.6, and there was full documentation available on which parts of .NET framework are supported in which API compatibility level. Not to mention, that there was an option to select the API compatibility level, which corresponded to the available Unity target framework values in Visual Studio.

Since none of that seems to be present in Unity 5 (yet?), you're left with trial and error. If your dependencies try to use any unsupported classes in .NET framework, Unity will fail with a pretty nondescript error:

Unhandled Exception: System.Reflection.ReflectionTypeLoadException: The classes in the module cannot be loaded.

You've probably noticed it's the same error as when there's an indirect assembly missing from the Unity project. There's some additional stack trace available in both cases, but there's no information in it, which would help you pinpoint the cause of the error. You'll have to check yourself whether you've forgotten to reference an assembly, or is there an unsupported class being used.

Copyright
Creative Commons License