This post should provide an up-to-date howto on how to move your gamelogic into a separate library with a separate solution while still being able to use that project's dll in your unity project and be able to use the full debugging capabilities on that external dll.

I tested this with Unity 5.4, 5.5, 5.6 and Visual Studio 2015 CE

The reason I wanted to separate those two projects is, that I tend to switch game engines a LOT but discovered that the logic itself is always the same.
So I desired an approach, where the game logic and datatypes for my strategy-game remains in a dedicated solution, completely engine-agnostic (which means no references to any gameengine related libraries) and re-usable on the go.

The issue with how Unity handles Solution files is, that every time you add a folder or a script inside Unity, it tends to re-generate the .sln and .csproj files, so any build-settings get lost, which makes it a pain to readd the external dependencies every time.
We'll use a build-script which hooks into the unity generation hooks to add our dependency to the Unity-Solution every time it gets generated. Also we add some post-build hooks to automatically copy the necessary library files into the Unity-Project's Assets directory so it is able to find the external dll.

  1. Create your library project with Visual Studio. Make sure the .Net Target Framework is set to 3.5. Other than that, you won't need to worry about this project other than adding your gamelogic free from any references to Unity or other Game Engines.

  2. Create a new Unity Project or take an existing one. Make sure to build both solutions and Builds at least once that all the necessary files and folders are created.

  3. Now you need to import the build hooks into your unity project. I found them myself somewhere on the internet and added them into a github repo here. Download the contents of the Repo and move the Editor folder with its contents into your UnityProject/Assets folder.
    "Editor" is a magic keyword which adds the included .cs files to the Unity Editor Plugin Workflow and automatically executes the included hooks.

  4. Edit the UnityProject/Editor/ExternalProject.xml file to suit your needs. Explanation for the configuration:

    assemblyName: The name of your external library assembly. Usually the name of the solution. If your library produces a foobar.dll, then "foobar" is the assemblyName.

    projectFilePath: Path to your .csproj file of your external library

    projectOutputPath: Path to the directory where the compiled .dll is placed. You can modify this to suit your needs, per default .dlls are placed into the Library directory root/bin/Debug. The \ at the end is mandatory!

    projectGuid: The guid of your project. You can find it if you open the .sln file with a text editor. Example picture: sln-guid (Including the brackets)

    monoConvertExe: Path to the pdb2mdb.exe as indicated by the example. Find it with your computer search. Unity/Editor folder usually contains one, altough you might need a more up-to-date version. If you want to spare you the headache, read the first FAQ/Troubleshooting entry.

  5. and the config is done.
    To re-generate the solution files, close Visual Studio, go to your Assets folder and delete the .sln file as well as the .csproj files (or move them somewhere to be safe) after that inside Unity click on "Assets > Open C# Project" and wait a few seconds for unity to generate the solutions.

    If all went well, there should be no error messages and VS2015 should start up, loading 3 projects into the project: 1) Your external Library, 2) The Unity specific Library code, 3) The Unity Project's Editor code which you won't need to touch most of the time.

    Make sure to check if the build hooks are correct in the properties of your Unity Project (Unityprojectname.CSharp) via "Rightclick > Properties > Build Events" There you should see 3 lines of commands in the Post-build event textbox.
    If not, maybe you are in the wrong project settings.

  6. Building:
    In VS hit "Build > Build Solution" and check the output.
    You should see the regular compilation output, including 2 copy-notices.
    Check your Unity Assets directory. This directory should now contain (ex. if your Library Name is "TestGame"):
    1) Your External Library dll file TestGame.dll
    2) Your External Library .pdb file TestGame.pdb
    3) Your External Library .mdb file TestGame.dll.mdb
    And the *.meta files unity usually auto-generates.

And that's it!
You can now reference your external library classes inside your unity project, set breakpoints and use the debugger as usual, all with a neat project separation!
Make sure to read at least the first FAQ entry!

You can find me on github
Or mailto:radon@rn86.de

FAQ, Troubleshooting and Shortcomings

  • Compilation fails, altough the copy commands seem correct and the files exist.

    The .dll and .pdb may already exist in the Assets directory, but the pdb -> mdb conversion may fail. That is because the pdb2mdb.exe unity provides inside its mono folder is outdated and may not be able to parse the generated Solution files.

    • To get a newer one, go to the mono download page, download and install the 32-bit mono library.
    • Download/Clone the Mono-Cecil release version 0.9.5 (Why this version in particular? If you run the pdb2mdb.exe inside the installed mono framework, it should throw an error that this particular version of Mono-Cecil is missing. If things don't work out, maybe you need another version)
    • After downloading the above mentioned source, extract it and open the .sln file. Build for net_2_0_Release target, head to the cecil-0.9.5\bin\net_2_0_Debug folder and copy everything into C:\path-to\Mono\lib\mono\2.0-api and C:\path-to\Mono\lib\mono\4.5
    • Locate pdb2mdb.exe inside your mono directory, I found mine at C:\Program Files (x86)\Mono\lib\mono\4.5\pdb2mdb.exe
    • Update the <monoConvertExe></monoConvertExe> path with your new one inside the Assets/Editor/ExternalProject.xml file, delete all unity solution files and re-generate them via "Assets > Open C# Project". Building should now work and a .mdb file should now exist in the Assets directory.
  • Unity doesn't keep up with changes I make in my library Project!

    If you make any changes to your library code, you need to build the project. Unity takes it's code and reference from the dll file inside the Assets directory, which gets updated once you hit Build in VS.

  • I am getting errors and warnings inside unity and can't open the project code at all

    I discovered that unity fails miserably, if files aren't there where it looks for them. It might help to compile the .dll file once via it's own solution and put the .dll file into the Assets directory by hand. Often this occurs once at project setup and should be solved, as soon as the build process just replaces over the existing files.

  • I made some changes to the project settings, but they get lost every now and then

    When you add a new Asset, that is relevant for the solution, as in, contains .cs files, unity regenerates the whole solution and overwrites the old one. To keep this from happening, only create script files through VisualStudio and use the Asset explorer only for Non-Script/Code-Assets.

  • All the project parts hinder my ability to use VersionControl because all the paths are different!

    You can add ExternalProject.xml to the ignored files and keep a local config for each participant and set the paths accordingly. This should suffice. In case I forgot something, you can contact me with a better approach on github.