Cannot step inside DLL outside of Assets even when mdb exists?

Greetings,

CONTEXT:
I’ve been fooling around lately with some platform layer and custom hot-reloading stuff. Basically write the entire ‘game’ code externally, compile in VS to a DLL, and load the functions in Unity via reflection. The DLL should sit outside of the “Assets” folder so that Unity doesn’t recompile when the DLL changes (yes I could use the Assembly locking API but I’d rather not complicate things if I could help it)

PROBLEM:
No matter what I do, I can’t seem to be able to debug/step into my code from Unity even if I manually generate an mdb file for the DLL. If however, I throw the DLL in Unity and try to step, it works just fine.

The only way I was able to generate an mdb is by using JB Evain’s tool here: [.[/URL]
All the other tools in mono/bin or mono/lib or MonoBleedingEdge or whatever, they all crash horribly with different type of exceptions/errors (e.g. “Runtime critical type System.RuntimeType not found”)

It’s very frustrating because the mdb that JB’s tool generate, is exactly the same size of the one that Unity generates when I throw the DLL in the Assets folder.

And yes I’ve tried testing without having any coroutines in the DLL cause I read about some issues regarding IEnumerator, didn’t help.

And I also tried putting the DLL under Assets, have Unity generate the .mdb for me, copy that .mdb to my external directory where my DLL exists, delete the DLL I just put in Assets, try debug, same issue.

I’m baffled because the code that you normally write in Unity gets compiled to an external DLL and put under Library/ScriptAssemblies anyways (which you could step into of course, with its own .mdb), so it’s not like I’m trying to do anything special here. I did try and put my DLL under ScriptAssemblies but Unity refreshes that folder everytime it recompiles, and no I was still not able to step even when the DLL was in there.

USING:
VS 2015 Community Edition
Unity 2017 1.1p2

QUESTION:
How can I actually step into a dll that’s located outside of the Assets folder?

CODE:
In Unity:

using System;
using System.IO;
using System.Reflection;
using UnityEngine;

public delegate void game_func_update(float dt);
public delegate void game_func_init();
public delegate void game_func_reload();

public class GameCodeDef
{
    public Assembly DLL;
    public game_func_init Game_Init;
    public game_func_update Game_Update;
    public game_func_reload Game_Reload;
    public bool IsValid;
}

public class Game : MonoBehaviour
{
    GameCodeDef GameCode;

    void Start()
    {
        GameCode = LoadGameCode();
        GameCode.Game_Init();
    }

    [ContextMenu("Reload")]
    void ReloadGameCode()
    {
        GameCode = LoadGameCode();
        GameCode.Game_Reload();
    }
 
    GameCodeDef LoadGameCode(string Filename="Game.dll")
    {
        GameCodeDef Result = new GameCodeDef();

        string AssetsPath = Application.dataPath;
        DirectoryInfo RootDir = Directory.GetParent(AssetsPath);
        string GameDLLPath = RootDir.FullName + "/GameDLL/" + Filename;
        try
        {
            byte[] DLLBytes = File.ReadAllBytes(GameDLLPath);
            Result.DLL = Assembly.Load(DLLBytes);
            Type GameType = Result.DLL.GetType("Game");

            BindingFlags Flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
            MethodInfo InitMethod = GameType.GetMethod("Game_Init", Flags);
            Result.Game_Init = Delegate.CreateDelegate(typeof(game_func_init), InitMethod) as game_func_init;

            MethodInfo UpdateMethod = GameType.GetMethod("Game_Update", Flags);
            Result.Game_Update = Delegate.CreateDelegate(typeof(game_func_update), UpdateMethod) as game_func_update;

            MethodInfo ReloadMethod = GameType.GetMethod("Game_Reload", Flags);
            Result.Game_Reload = Delegate.CreateDelegate(typeof(game_func_reload), ReloadMethod) as game_func_reload;

            Result.IsValid = true;
        }
        catch (Exception e)
        {
            Debug.LogError("Could not load Game.dll: " + e);
            Result.Game_Update = (float dt) => { Debug.Log("Dummy Update"); };
            Result.Game_Init = () => { Debug.Log("Dummy Init"); };
            Result.Game_Reload = () => { Debug.Log("Dummy Reload"); };
            Result.IsValid = false;
        }

        return(Result);
    }

    void Update()
    {
        float dt = Time.deltaTime;
        GameCode.Game_Update(dt);
    }
}

In the DLL:

using System;
using UnityEngine;
using Random = UnityEngine.Random;

public class PlayerDef
{
    public string Name;
    public int Id;
    public Transform Transform;

    public override string ToString()
    {
        return string.Format("Name={0}, Id={1}", Name, Id);
    }
}

public class GameStateDef
{
    public PlayerDef Player;
    public float T;
}

public class Game
{
    static GameStateDef GameState;

    public static void Game_Update(float dt)
    {
        if (Input.GetKeyDown(KeyCode.P))
        {
            Debug.LogError("Player: " + GameState.Player);
        }

        if (Input.GetKeyDown(KeyCode.R))
        {
            GameState.Player.Id = Random.Range(1, 100);
            GameState.Player.Name = (new string[] { "ALI", "JEFF", "JON", "PER"})[Random.Range(0, 4)];
        }
   
        Transform Target = GameState.Player.Transform;
        float Speed = 2;
        Vector3 OP = Target.localPosition;
        Vector3 TP = OP + Random.insideUnitSphere * 10;
        if (GameState.T < 1)
        {
            Target.position = Vector3.Lerp(OP, TP, GameState.T);
            GameState.T += Time.deltaTime * Speed;
        }
        else
        {
            GameState.T = 0;
        }
    }

    public static void Game_Init()
    {
        Debug.LogError("Game_Init");

        GameState = new GameStateDef();
        GameState.Player = new PlayerDef();
        GameObject PlayerObject = GameObject.CreatePrimitive(PrimitiveType.Sphere);
        GameState.Player.Transform = PlayerObject.transform;
    }

    public static void Game_Reload()
    {
        Debug.LogError("Game_Reload");
    }
}

Cheers!](pdb2mdb for Visual Studio 2015 · GitHub)

Thanks to @jbevain turns out I had to call Assembly.LoadFile(path) instead of Assembly.Load(bytes) – First one loads the debug symbols, the other one doesn’t.