Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Possible to early attach debuggers to Unity players?

Discussion in 'Editor & General Support' started by Paul_Bronowski, Nov 9, 2015.

  1. Paul_Bronowski

    Paul_Bronowski

    Joined:
    Sep 3, 2014
    Posts:
    55
    Greetings,

    I'm looking for a way to early attach a debugger to the Unity WindowsPlayer. Attach would probably need to happen just after the engine exposes the debug port, before it starts loading managed assemblies. Typically this is done in one of two ways 1) A switch or build flag activates a modal 'attach debugger now' prompt. 2) A switch or build flag tells the app to start a debugger and attach it. My preferred Unity debugger is Visual Studio 2015 (via UnityVS). I've tried starting my .exe in a debug session, but that's debugging the native runtime, and not hooked to the exposed Unity debug port for managed debugging. Apologies if I missed this info in the docs/forums. Any pointers would be appreciated.

    Thanks,
    Paul
     
  2. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,555
    What are you trying to debug?

    Just a couple of ideas off the top of my idea:

    1. Implement a [InitializeOnLoad] method and create some sort of modal window there (or just block for a long time, allowing you to attach a debugger. This happens early on, but only after script assemblies have been loaded (otherwise, how would your code be able to run... ?)

    2. (NOT SURE THIS IS POSSIBLE) Set up a named breakpoint in VS2015. You'd need to look up for one of the earliest Mono methods that gets called when Unity runs. Setup a breakpoint with that name and wait for it to hit. I am not sure VS allows setting up breakpoints for stuff you don't have the code for, but worth trying.

    In any case, it would be helpful to understand what you are trying to do.
     
  3. Paul_Bronowski

    Paul_Bronowski

    Joined:
    Sep 3, 2014
    Posts:
    55
    Thanks for the reply/interest. The main entry point into our game is our Loader singleton, which is responsible for async loading our startup SubScenes. Due to a bug in the Advanced Additive Scenes plugin, which only manifests at runtime (not in Editor), I needed a way to early attach and debug said plugin code. I ended up going with a conditional compiled solution (below) that fires up a LoaderDebugger UI ('Attach debugger now (Ok)'), which calls back to Loader to start loading the SubScenes. I was able to find the bug, work around it and communicate it back to the owner, so I'm unblocked.

    However, this is a sloppy solution, IMHO. What if I had a bug that happened only at runtime and only due to one of my assemblies not being able to load (failed strong name checks, platform problems, corruption, etc.)? It would be tough to determine the exact problem, if I can't trap the problem/exception in a debugger.

    Your suggestion of using [InitializeOnLoad] (InitializeOnLoadMethodAttribute) won't work, I believe. That's for executing Editor-only code. Named VS breakpoints aren't going to work, I think. We need to be attached to the Unity runtime debug port in order to catch problems in our code, and we aren't attached early enough.

    It would be nice to see an 'early attach debug' build option from Unity. It would inject code that halts loading and puts up a modal 'Attach debugger now (Ok)' dialog, just after the managed App Domain is created and before our managed assemblies start loading. That's typically the right sort of way for hosted runtimes to do it. I wouldn't be surprised if Unity has such a mechanism, but they don't expose it.

    Thanks,
    Paul


    Code (CSharp):
    1.         /// <summary>
    2.         /// Awake this instance
    3.         /// </summary>
    4.         internal void Awake()
    5.         {
    6.             // Instantiate singletons
    7.             PreFabFactory.CreateInstance(this.PreFabFactoryPreFab);
    8.             CoroutineScheduler.CreateInstance(PreFabFactory.Instance.CoroutineSchedulerPreFab);
    9.             HUDManager.CreateInstance(this.HUDManagerPreFab);
    10.  
    11.             // Start our general dispatcher so that we can process GameLoad and GameStart Commands
    12.             CommandDispatcher<Command>.CreateSingletonInstance(true, true);
    13.  
    14. #if DEBUG_LOADERDEBUGGER
    15.             LoaderDebugger.Create(this);
    16. #endif
    17.         }
    18.  
    19.  
    20.         /// <summary>
    21.         /// Start this instance
    22.         /// </summary>
    23.         internal void Start()
    24.         {
    25.             // If we're debugging, do nothing. LoaderDebugger will call us back.
    26. #if !DEBUG_LOADERDEBUGGER
    27.             this.OnStart();
    28. #endif
    29.         }
     
  4. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,555
    This is just one type of problem, but generally i hate to break it to you... this is a closed source engine with lots of different subsystems. Any one of these could fail without you having a single clue what was the root cause.
    Specifically with assembly loading i suppose you'd see a message in the player log for what's going on.

    I meant this attribute: http://docs.unity3d.com/ScriptReference/RuntimeInitializeOnLoadMethodAttribute.html
    It's the same as the one i suggested, but only for runtime. It will be called as soon as the Mono runtime is loaded.

    BTW - i believe that the Mono soft debugger (the debugger Unity uses) is loaded early on when the engine is started (when the splash is shown i think), but before any assemblies are loaded. It can be a bit tricky, but i think if you time things right, you can attach to it using MonoDevelop / VS and then debug whatever assembly loading issues you may have.