Configuring Cross-platform DLL’s in #Unity3d automatically #UnityTips

Many Unity devs don’t use DLL’s, but they save a lot of time and effort. Unity hasn’t documented much of the process, but it’s surprisingly easy when you know how.

Previously, I showed how to use MonoDevelop to make C# DLL’s that work in all versions of Unity, and intelligently switch between different versions of the Unity SDK’s.

Today we’re going to finish by automating the setup, so that you can edit source code and ship C# DLL’s from any version of Unity, on any computer, on any Operating System – and they seamlessly interact with all the other people on your project (no conflicts, no errors).

Recap: When to use C# DLL’s?

NB: you can also make native-code DLL’s, written in C++ etc – but that’s a much more specialized situation, and requires a lot more work. We’re only covering the simple setup here: non-native code.

DLL’s are essential if you’re shipping re-usable code for other people to use. The primary example is the Asset Store: all code Assets should ship as DLL’s, with the source code in a separate folder. Gamedevs want (and deserve) a simple drag/drop file that Just Works – they don’t want to recompile your source code – or have it show up in text searches – every time they edit their own source.

They also reduce build times on larger projects: Unity generally tries to recompile EVERY source file all the time, greatly slowing down development. DLL’s act as a perfect cache for features that you’ve finished working on.

Problems

NB: I’m doing this all in MonoDevelop specifically because it’s guaranteed to be installed with all versions of Unity, on all platforms. That makes it fully automatable (even though I use Rider or Visual Studio for my own game scripts).

Specific to Unity, we have three problems:

  1. Unity’s #compile-time directives are private, and they failed to integrate them into MonoDevelop. e.g. #if UNITY_EDITOR won’t work in MonoDevelop fix that using the previous article
  2. Unity’s own DLL’s (needed by MonoDevelop) are stored in different locations depending which version of Unity you’re running, and in different ways for differnt OS’s
  3. MonoDevelop has major problems trying to use a CSPROJ file with a team working on different OS’s

Helping MonoDevelop find the correct UnityEngine.DLL and UnityEditor.DLL

First problem: Unity’s version of MonoDevelop is poorly integrated with Unity, and requires an absolute file location for Unity’s DLL’s. Since there is no standardization of folder names on Windows and Mac, this is going to cause problems: we cannot use the same folder name everywhere.

But we can do it for Windows, and separately for Mac. So let’s start there. The basic approach is the same for versions and OS’s: we use symlinking.

Everyone on your project needs to create a new shortcut, at the same location. Windows users create it in one place, Mac users in a different place.

Windows folder

OS X Folder
Do not create these folders by hand; use the special commands described below
C:\Program Files (x86)\Unity5 Applications/Unity5

Note: these are fake, virtual, folders. The purpose is to “point to” the actual version of Unity you’re developing with – 5.0.0, 5.3.4, 5.6.6, etc – in a location that never changes (because MonoDevelop cannot cope with change). You can manually update it when you switch over to a new version of Unity, and all your Unity projects will automatically pick up the change.

If you forget to update it? Everything will still work, but you’ll be unable to use any new API’s in the newer version of Unity. That’s why I put the “5” in Unity-5 – because the API’s don’t change much during a major version of Unity (compared to the differences between 4 and 5, or 5 and 2017).

Windows linking

You need to know the version of Unity you’ll start with. e.g. if you have installed Unity 5.6.6 to the folder: “D:\Development\Unity\Unity-5.6.6\”

  1. Open an Administrator Command Prompt:
    • Press Windows
    • Type “command” but don’t hit enter
    • Right click on the Command Prompt app
    • Select “Run as Administrator”
  2. Move to the folder you want to store the virtual link in:
    • cd “\Program Files (x86)”
  3. Create the link:
    • mklink Unity5 “D:\Development\Unity\Unity-5.6.6\”

OS X linking

You need to know the version of Unity you’ll start with. e.g. if you have installed Unity 5.6.6 to the folder: “\Applications\Unity-5.6.6\”

  1. Run Terminal
  2. Type: sudo ln -s \Applications\Unity-5.6.6\ \Applications\Unity5\

Update MonoDevelop so it can cope with multiple OS’s

This bit is slightly annoying to maintain: you need to duplicate the C# project and have an OSX version and a Windows version. Generally the only thing that changes over time is the included files – and it’s very easy/quick to add those by hand if they get out of sync. But it’s not 100% automatic, I’m afraid.

You have 2 or 3 files to duplicate:

  1. MyProjectName.sln
  2. MyProjectName/MyProjectName.csproj
  3. OPTIONAL: MyProjectNameEditor/MyProjectNameEditor.csproj

Updating the sln file

Duplicate it, and rename both versions, e.g.:

  • MyProjectName-win.sln
  • MyProjectName-osx.sln

Somewhere at the top, you’ll see something like this:

# Visual Studio 2012
Project(“{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}”) = “MyProjectName”, “MyProjectName\MyProjectName.csproj”, “{12EAD028-E1C5-4308-91BE-62FF25B58993}”
EndProject
Project(“{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}”) = “MyProjectNameEditor”, “MyProjectNameEditor\MyProjectNameEditor.csproj”, “{F5295406-71A4-4B29-8C37-B27DC1B0FF53}”
EndProject

Change the windows version to have “-win” in the csproj filename, and change OS X version to have “-osx” in the csproj filename.

…-win.sln

e.g. Here is my changed version for windows (inside the file MyProjectName-win.sln)

# Visual Studio 2012
Project(“{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}”) = “MyProjectName”, “MyProjectName\MyProjectName-win.csproj“, “{12EAD028-E1C5-4308-91BE-62FF25B58993}”
EndProject
Project(“{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}”) = “MyProjectNameEditor”, “MyProjectNameEditor\MyProjectNameEditor-win.csproj“, “{F5295406-71A4-4B29-8C37-B27DC1B0FF53}”
EndProject

…-osx.sln

e.g. Here is my changed version for OS X(inside the file MyProjectName-osx.sln)

# Visual Studio 2012
Project(“{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}”) = “MyProjectName”, “MyProjectName\MyProjectName-osx.csproj“, “{12EAD028-E1C5-4308-91BE-62FF25B58993}”
EndProject
Project(“{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}”) = “MyProjectNameEditor”, “MyProjectNameEditor\MyProjectNameEditor-osx.csproj“, “{F5295406-71A4-4B29-8C37-B27DC1B0FF53}”
EndProject

Updating the csproj file(s)

Go into each subfolder that has a MonoDevelop sub-project (by default, there’s only one. But if you have editor scripts, Unity requires you to have a second folder, and to build a separate DLL that links to Unity’s UnityEditor.DLL).

Duplicate the csproj file and rename both versions, e.g.:

  • MyProjectName-win.csproj
  • MyProjectName-osx.csproj

Updating …-win.csproj

Near the bottom, you will find some settings that look like this:

<ItemGroup>
<Reference Include=”System” />
<Reference Include=”UnityEngine”>
<HintPath>C:/Program Files (x86)/Unity5/Editor/Data/Managed\UnityEngine.dll</HintPath>
</Reference>
<Reference Include=”UnityEditor”>
<HintPath>C:/Program Files (x86)/Unity5/Editor/Data/Managed\UnityEditor.dll</HintPath>
</Reference>
</ItemGroup>

…if you have an Editor project as well…

…you’ll also have to update the cross-project link embedded in this file. It looks something like this:

<ItemGroup>
<ProjectReference Include=”..\SnapAndPlug\SnapAndPlug.csproj”>
<Project>{12EAD028-E1C5-4308-91BE-62FF25B58993}</Project>
<Name>SnapAndPlug</Name>
</ProjectReference>
</ItemGroup>

So change it to:

<ItemGroup>
<ProjectReference Include=”..\SnapAndPlug\SnapAndPlug-win.csproj”>
<Project>{12EAD028-E1C5-4308-91BE-62FF25B58993}</Project>
<Name>SnapAndPlug</Name>
</ProjectReference>
</ItemGroup>

Updating …-osx.csproj

Near the bottom, you will find some settings that look like this:

<ItemGroup>
<Reference Include=”System” />
<Reference Include=”UnityEngine”>
<HintPath>\Applications\Unity5\Unity.app\Contents\Managed\UnityEngine.dll</HintPath>
</Reference>
<Reference Include=”UnityEditor”>
<HintPath>\Applications\Unity5\Unity.app\Contents\Managed\UnityEditor.dll</HintPath>
</Reference>
</ItemGroup>

…if you have an Editor project as well…

…you’ll also have to update the cross-project link embedded in this file. It looks something like this:

<ItemGroup>
<ProjectReference Include=”..\SnapAndPlug\SnapAndPlug.csproj”>
<Project>{12EAD028-E1C5-4308-91BE-62FF25B58993}</Project>
<Name>SnapAndPlug</Name>
</ProjectReference>
</ItemGroup>

So change it to:

<ItemGroup>
<ProjectReference Include=”..\SnapAndPlug\SnapAndPlug-osx.csproj”>
<Project>{12EAD028-E1C5-4308-91BE-62FF25B58993}</Project>
<Name>SnapAndPlug</Name>
</ProjectReference>
</ItemGroup>

Finis<

From now on, your windows developers should open the “-win” csproj / sln file, and your OS X developers should open the “-osx” csproj / sln file, and all will be well. Config files will be stable across both OS’s, and both platforms automatically build DLLs that work on all platforms – so you don’t have to worry about who built each new version of the DLL file(s).

Leave a Reply

Your email address will not be published. Required fields are marked *