Working with external class libraries in Unity and Rider

Yesterday, we posted about a new feature in Rider 2017.3.1 – debugging third party code in Mono. This feature nicely rounds out Rider’s support for a specific Unity workflow – building and debugging external class libraries. Let’s take a look at how Rider can help here.

Unity will of course compile any C# scripts that are in the main Unity project, and it will generate the correct debugging information as part of the normal build process. Rider already has great support for debugging normal Unity C# scripts, and will automatically configure itself to attach the debugger to the Unity editor instance.

But Unity also supports the idea of an “external class library“. This is simply a .NET class library that Unity will automatically reference once it’s copied into one of Unity’s Assets folders.

Rider provides a project template to help get started with an external library. This will create a standard, new .NET Framework class library, but it will also include a reference to UnityEngine.dll. You can specify the path in the template dialog, and it is pre-populated to a path pointing to your install of Unity. (Make sure to select a compatible .NET Framework version, or Unity won’t see any components!)

Unity class library template dialog

But things can get a bit awkward with debugging.

The problem is that Unity’s version of Mono requires debugging information to be in Mono’s own .dll.mdb file format, and if the Mono runtime can’t load this file, debugging is not available.

Don’t worry. Rider has you covered.

If you tell Rider to use an older version of the Mono toolset, such as the one that ships with Unity, then Mono’s own C# compiler will generate the .dll.mdb file and all is good. You can select the Unity Mono toolset in the Build, Execution, Deployment | Toolset and Build preferences page. The downside to this approach is that you are limited to the version of C# supported by the compiler in that Mono toolset, which for Unity’s toolset is C# 6.

Note that even though Unity’s support for anything over C# 4 is experimental, it is usually safe to use a new version of C# for your external libraries, as most of the new language features are backwards compatible.

If you’re working on Windows, Rider will by default use the .NET Framework to build the class library, and this generates a .pdb file instead of the required .dll.mdb file. In this situation, Rider’s Unity editor plugin will automatically run JB Evain’s very useful pdb2mdb program and generate a compatible .dll.mdb file whenever the assembly is updated.

And finally, we get to the more common scenario for non-Windows developers – compiling with the system installed version of Mono, which is Rider’s default toolset choice. To make life more interesting, Mono have started shipping Microsoft’s C# compiler. This allows you to use C# 7 features, but unfortunately, it generates a .pdb file that isn’t compatible with Unity’s version of Mono, or the pdb2mdb program (it’s a “portable PDB”, which is a completely different format to the .pdb files on Windows). In this scenario, debugging on Mono is essentially impossible – we don’t generate the correct format, and we can’t convert to it either.

And this is where Rider’s new debugging capabilities come in.

Rider’s newly added ability to debug code that we don’t have debugging information for allows us to debug external libraries that don’t have the correct .dll.mdb file, by treating them like we treat any other library that we don’t have debug information for – by automatically decompiling code on-the-fly, and debugging the decompiled code.

This allows us to step into functions, set breakpoints and view and set locals and variables. We can even double click on a stack frame and see the code below us in the stack.

Debugging external library

Download Rider 2017.3.1 today and see how Rider can help with your Unity projects and external class libraries. Let us know how you get on, and please let us know any suggestions you have to improve our Unity support.

image description