sarbian Posted March 29, 2015 Share Posted March 29, 2015 (edited) Edit: Those instruction are partially outdated for KSP 1.8. Have a look at the post following this one and specifically this one if you are on Windows. As we all know debugging plugin in KSP is mostly done with endless spam of Debug.Log or a bunch of custom windows we have to build. We also have angavrilov method but it require to recompile the whole mono and is a bit scary. So here is the result of a couple of days of experiment on my side to get a simple method working. So how do we get debugging to work for KSP ? Simply by using the tool that unity provides us. Unity has a debugging system for games that runs in development mode, which is not the case of KSP by default. So here is how to get that (Linux users read that part and I will explain the difference for you further down. OSX user read this post) KSP First you need a Unity installation (or here if the version ends with px) using the exact same version as your current KSP (For 1.1 you need Unity 5.2.4f1). That version is in the first line of the output_log.txt/Player.log. Go to your Unity install for that version ( "C:\Program Files\Unity\Editor" most likely) and then go in the "Data\PlaybackEngines\windowsstandalonesupport\Variations\win64_development_mono" sub-directory. Copy the "player_win.exe" file to your KSP dev install (next to KSP.exe) Rename that "player_win.exe" to "KSP_x64_Dbg.exe" Open a command prompt in that directory (shift right clic in the empty space of the explorer and select "open command window here". In it enter the command "mklink /J KSP_x64_Dbg_Data KSP_x64_Data". You will now have a KSP_x64_Dbg_Data that points to the stock KSP_x64_Data. Get this file and put it in the KSP_x64_Data directory (it makes the mono debugger starts its listening port) Launch KSP with the KSP_x64_Dbg.exe and check that you have "Development Build" in your lower right corner Get this zip and put its content somewhere. For me it will be "C:\Games\Tools\pdb2mdb" If you compile with VS you have to generate the mono debug information. To generate them I add some command in the project post-build event command line. Here is what mine looks like for MJ "C:\Games\Tools\pdb2mdb\pdb2mdb.exe" "$(TargetFileName)" xcopy /Y "$(TargetPath)" "C:\Games\ksp-win_dev\GameData\MechJeb2\Plugins\" xcopy /Y "$(TargetDir)$(TargetName).pdb" "C:\Games\ksp-win_dev\GameData\MechJeb2\Plugins\" xcopy /Y "$(TargetDir)$(TargetName).dll.mdb" "C:\Games\ksp-win_dev\GameData\MechJeb2\Plugins\" Compile your plugin in "Debug" configuration to get the "MyPlugin.dll" AND the "MyPlugin.dll.mdb" (Generated with pdb2mdb from "MyPlugin.pdb" if you use VS. Or by mono if you use MonoDevelop or mono cmd line). Copy them in your usual GameData dir if your post build command does not already do it We are now ready on KSP side. Visual Studio You need a version that allows plugin. So either a VS Pro+ or Visual Studio Community (it is free and Unity most likely already installed it). Make sure you check the Tools for Unity and NET 3.5 options in the install. Once you have that you will have a "Attach Unity Debugger" in the Debug menu. So launch KSP and use that menu to attach VS to it. You should get an orange bar at the bottom of VS and the context should switch to debugging. You now have all the usual debugging tools (breakpoints, step by step, watches). You may want to activate "exception support" to have a the debugger break on exception (Tools => Options => "Tools for Unity" => "Exception Support") MonoDevelop In the "Run" menu you have "Attach to Process". It opens a windows where you should have "Unity Debugger" selected on the lower part and you can select your KSP process to attach to. It should switch to the debugging context Profiling Now that KSP use Unity 5 we can use the Unity Profiler for free. Launch KSP in développer mode and launch an empty Unity project. In the "Window" menu select Profiler. The profiler opens and in the "Active Profiler" at the top of the window you can select your running KSP instance. By default you will only see the MonoBehavior methods (Update, FixedUpdate, ...) but you can add calls in your code to profile anything. First make sure your code is compiled with the "ENABLE_PROFILER" conditional (add it in the build config). Then in your code add pairs of "Profiler.BeginSample("MyLabel");" and "Profiler.EndSample();". Be aware that if a frame take too long the profiler skip it, so you can't profile really slow method that last a single frame.An example from MJ : Profiler.BeginSample("vesselState"); ready = vesselState.Update(vessel); Profiler.EndSample(); The profiler will now show you info for this exact call somewhere in its hierarchy. (there is a search field to find it). A warning : profiling is complex and result are often more complex to interpret than you may think. Linux and OSX The steps are the same. The only difference is the directory where you get the executable. If you are on Linux you will just need to copy some files, so use a VM to install Unity or ask a friend. - OSX : <Unity.app>/Contents/PlaybackEngines/MacStandaloneSupport/Variations/universal_development_mono/UnityPlayer.app - Linux : <Unity>/Data/PlaybackEngines/linuxstandalonesupport/linux32_withgfx_development or linux64_withgfx_development. Get the LinuxPlayer file, copy it to your KSP install and rename it KSP.x86 or KSP.x86_64 depending on the directory you got it from and make sure you set it +x Missing Unity debugger for MonoDevelop (Custom install or Linux) If you installed MonoDevelop yourself you most likely do not have the Unity Debugger installed. Go in Tools->Addin Manager and install the Unity Soft Debugger addon (I did not test those steps so I would like some feedback) Edited November 18, 2019 by sarbian Quote Link to comment Share on other sites More sharing options...
godarklight Posted March 29, 2015 Share Posted March 29, 2015 I for one welcome our new debugging overlord.Thanks, may this type of code be gone forever! private void ProcessNewVesselMessages() { int throwLine = 0; try { throwLine = 1; Dictionary<Guid, double> removeList = new Dictionary<Guid, double>(); throwLine = 2; lock (vesselRemoveQueue) { throwLine = 3; foreach (KeyValuePair<Guid, Queue<VesselRemoveEntry>> vesselRemoveSubspace in vesselRemoveQueue) { throwLine = 4; while (vesselRemoveSubspace.Value.Count > 0 ? (vesselRemoveSubspace.Value.Peek().planetTime < Planetarium.GetUniversalTime()) : false) { throwLine = 5; VesselRemoveEntry removeVessel = vesselRemoveSubspace.Value.Dequeue(); throwLine = 6; RemoveVessel(removeVessel.vesselID, removeVessel.isDockingUpdate, removeVessel.dockingPlayer); throwLine = 7; removeList[removeVessel.vesselID] = removeVessel.planetTime; throwLine = 8; } } } throwLine = 9; foreach (KeyValuePair<string, Queue<KerbalEntry>> kerbalProtoSubspace in kerbalProtoQueue) { throwLine = 10; while (kerbalProtoSubspace.Value.Count > 0 ? (kerbalProtoSubspace.Value.Peek().planetTime < Planetarium.GetUniversalTime()) : false) { throwLine = 11; KerbalEntry kerbalEntry = kerbalProtoSubspace.Value.Dequeue(); throwLine = 12; LoadKerbal(kerbalEntry.kerbalNode); throwLine = 13; } } throwLine = 14; foreach (KeyValuePair<Guid, Queue<VesselProtoUpdate>> vesselQueue in vesselProtoQueue) { throwLine = 15; VesselProtoUpdate vpu = null; throwLine = 16; //Get the latest proto update while (vesselQueue.Value.Count > 0 ? (vesselQueue.Value.Peek().planetTime < Planetarium.GetUniversalTime()) : false) { throwLine = 17; VesselProtoUpdate newVpu = vesselQueue.Value.Dequeue(); throwLine = 18; if (newVpu != null) { throwLine = 19; //Skip any protovessels that have been removed in the future if (removeList.ContainsKey(vesselQueue.Key) ? removeList[vesselQueue.Key] < vpu.planetTime : true) { throwLine = 20; vpu = newVpu; throwLine = 21; } } } throwLine = 22; //Apply it if there is any if (vpu != null ? vpu.vesselNode != null : false) { throwLine = 23; LoadVessel(vpu.vesselNode, vpu.vesselID); throwLine = 24; } } throwLine = 25; foreach (KeyValuePair<Guid, Queue<VesselUpdate>> vesselQueue in vesselUpdateQueue) { throwLine = 26; VesselUpdate vu = null; throwLine = 27; if (vesselQueue.Value == null) { Debug.Log("LINE27THROW vesselQueue.Value is null!"); } if (vesselQueue.Value.Count > 0) { if (vesselQueue.Value.Peek() == null) { Debug.Log("LINE27THROW vesselQueue.Value.Peek() is null!"); continue; } } //Get the latest position update while (vesselQueue.Value.Count > 0 ? (vesselQueue.Value.Peek().planetTime < Planetarium.GetUniversalTime()) : false) { throwLine = 28; vu = vesselQueue.Value.Dequeue(); throwLine = 29; } throwLine = 30; //Apply it if there is any if (vu != null) { throwLine = 31; HackyInAtmoLoader.fetch.SetVesselUpdate(vesselQueue.Key, vu); throwLine = 32; vu.Apply(); throwLine = 33; } } } catch (Exception e) { DarkLog.Debug("VESSEL UPDATE THROW: Threw on line " + throwLine + ", exception: " + e); } } Quote Link to comment Share on other sites More sharing options...
taniwha Posted March 29, 2015 Share Posted March 29, 2015 heh, I do similar with Debug.Log("a") b c d...btw, for those compiling using gmcs (usually using Makefiles: just add -debug to the gmcs command line). Quote Link to comment Share on other sites More sharing options...
sarbian Posted March 29, 2015 Author Share Posted March 29, 2015 Edited to show that the command line for the mdb generation must be launched from the dll dir (thanks ilo) Quote Link to comment Share on other sites More sharing options...
ilo Posted March 29, 2015 Share Posted March 29, 2015 This will definitelly change and improve the addon development a lot! thank you Sarbian Quote Link to comment Share on other sites More sharing options...
NathanKell Posted March 29, 2015 Share Posted March 29, 2015 Well dang, that's pretty awesome indeed! Kudos sarbian! Quote Link to comment Share on other sites More sharing options...
Teknoman117 Posted March 29, 2015 Share Posted March 29, 2015 Oh wow. This will be absolutely fantastic. So much better than that old project where you had to build a modified version of the Mono libraries. Edit: I'm stupid. You linked the archives.- - - Updated - - -Actually, could you email me the linux executables? I'm in the middle of a project with Unity 4.6 and don't particularly want to risk breaking my dev environment by reverting Unity and then going back Quote Link to comment Share on other sites More sharing options...
Teknoman117 Posted March 29, 2015 Share Posted March 29, 2015 (edited) Okay, so, just my luck it doesn't work for me...Did everything you said, got the "development version" watermark in the KSP window and everything. However, nothing happens when I try to attach to the process (I'm guessing it failed to attach). However, it sometimes opens the developer console with a long list of the same message about failing to wait on a semaphore (something which seemed to be mentioned in angavrilov's commit log for his debugger. If i try to set a breakpoint anywhere, a couple seconds later mono pops up a dialog with "Debug operation failed." I verfied that in this case I hit attach before the connection timed out.This is what the executable spits out for me as well.Set current directory to /home/nathaniel/Projects/ksp/0.90.0Found path: /home/nathaniel/Projects/ksp/0.90.0/KSP.x86_64Mono path[0] = '/home/nathaniel/Projects/ksp/0.90.0/KSP_Data/Managed'Mono path[1] = '/home/nathaniel/Projects/ksp/0.90.0/KSP_Data/Mono'Mono config path = '/home/nathaniel/Projects/ksp/0.90.0/KSP_Data/Mono/etc'PlayerConnection initialized from /home/nathaniel/Projects/ksp/0.90.0/KSP_Data (debug = 0)PlayerConnection initialized network socket : 0.0.0.0 55502Multi-casting "[IP] 192.168.1.69 [Port] 55502 [Flags] 3 [Guid] 661409256 [EditorId] 803286173 [Version] 1048832 [Id] LinuxPlayer(192.168.1.69) [Debug] 1" to [225.0.0.222:54997]...Waiting for connection from host on [192.168.1.69:55502]...Timed out. Continuing without host connection.Using monoOptions --debugger-agent=transport=dt_socket,embedding=1,defer=y,address=0.0.0.0:56256PlayerConnection already initialized - listening to [192.168.1.69:55502] Edited March 29, 2015 by Teknoman117 Quote Link to comment Share on other sites More sharing options...
sarbian Posted March 30, 2015 Author Share Posted March 30, 2015 I am afraid I can't help much here. Others reported that it works for them on Linux. Try switching the mono lib for the one that angavrilov built, his fix may help and you should still get the easier debugging. Quote Link to comment Share on other sites More sharing options...
TriggerAu Posted April 6, 2015 Share Posted April 6, 2015 Excellent stuff Sarbian, worked first time for me - after I got the right Unity version (facepalm). Thanks heaps Quote Link to comment Share on other sites More sharing options...
FreeThinker Posted April 29, 2015 Share Posted April 29, 2015 This should be a sticky Quote Link to comment Share on other sites More sharing options...
sarbian Posted April 29, 2015 Author Share Posted April 29, 2015 (edited) No point to sticky it since it does not seems to work with 1.0 (at least it did not in exp, I did not test with the release). I'll have a go at making it work again soonish since it is hard to got back to printing stuff once you had better. Edited April 29, 2015 by sarbian Quote Link to comment Share on other sites More sharing options...
Slother Posted May 3, 2015 Share Posted May 3, 2015 Has someone managed to get it working again?Using the development version of the unity player causes a bunch of errors on startup and prevents ksp from starting up.I tried it on KSP version 1.0.2.842 with Unity version 4.6.4f1.Error messages:Serialization depth limit exceeded at 'ThermalLink'. There may be an object composition cycle in one or more of your serialized classes.Serialization depth limit exceeded at 'OcclusionData'. There may be an object composition cycle in one or more of your serialized classes.and lots of these:ArgumentException: PropertyToID can only be called from the main thread.Constructors and field initializers will be executed from the loading thread when loading a scene.Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function. at (wrapper managed-to-native) UnityEngine.Shader:PropertyToID (string) at HighLogic..cctor () [0x00000] in <filename unknown>:0 Rethrow as TypeInitializationException: An exception was thrown by the type initializer for HighLogic Quote Link to comment Share on other sites More sharing options...
TAz00 Posted May 6, 2015 Share Posted May 6, 2015 Anyone get this to work with 1.0 yet? Quote Link to comment Share on other sites More sharing options...
sarbian Posted May 6, 2015 Author Share Posted May 6, 2015 No. I will post if I make it work, don't worry. Quote Link to comment Share on other sites More sharing options...
parachutingturtle Posted May 6, 2015 Share Posted May 6, 2015 I'm getting the same kinds of errors as Slother I was so excited when I saw this thread, what a bummer. Quote Link to comment Share on other sites More sharing options...
FW Industries Posted May 7, 2015 Share Posted May 7, 2015 Holy crap, I got it to work. I used Cecil to patch the assembly and fix the exceptions. Removed the static initializers and moved them to Awake() like the exceptions suggested. I still can't quite believe that actually worked.Run this in KSP_Data\Managed, it will patch Assembly-CSharp.dll: https://dl.dropboxusercontent.com/u/7121093/ksp-mods/KSP%5B1.0.2%5DKspDevModePatcher%5BMay07%5D.zipSource and license included.After that it just works as described in OP. The errors about deserialization with ThermalLink and OcclusionData are probably just red herrings. I get those even in release mode.There were a few more exceptions that only popped up later in-game. So there might be a few more I didn't run into yet, but they can probably be fixed the same way. Quote Link to comment Share on other sites More sharing options...
sarbian Posted May 7, 2015 Author Share Posted May 7, 2015 (edited) I was just looking into doing that ! Great to see that it works. I know where the other change are needed and I ll have an other look tomorrow Thanks !Edit : You missed MapView ModuleAblator PQSMod_MaterialQuadRelative SkySphereControl. I ll fix that The deserialization errors are real problems but as you said they are in release too.Edit2 : I could not go to sleep with so near. Get the updated full tool to patch the dll.Again many thanks to FW Industries Edited May 8, 2015 by sarbian Quote Link to comment Share on other sites More sharing options...
sarbian Posted May 8, 2015 Author Share Posted May 8, 2015 I updated the patching exe again and it seems to work fine on my end now. Quote Link to comment Share on other sites More sharing options...
TAz00 Posted May 8, 2015 Share Posted May 8, 2015 (edited) Amazing, testing asap. KSP loads into development build now on 1.0. Can't wait to test out when i get home. Attach unity debugger atleast connects in VSS.*Edit, my god, it's full of breakpoints Edited May 8, 2015 by TAz00 Tested it Quote Link to comment Share on other sites More sharing options...
TAz00 Posted May 8, 2015 Share Posted May 8, 2015 (edited) It sort of works alright. I did get an error whenever i try to step into this piece of code. I can break on the function call, but it errors out in the debug log as soon as you step into it. And code just continues without input. Until function breakpoint is triggered again. private void CloneCurrentVessel() { Vessel original = FlightGlobals.ActiveVessel; ProtoVessel pv = new ProtoVessel(original); Guid vesselId = pv.vesselID; //Offending line Vessel newVessel = FlightGlobals.Vessels.Where(i => i.protoVessel.vesselID.Equals(vesselId)).First(); }[Exception]: TypeLoadException: Could not load type 'System.Func`2' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.I've tried compiling with the modified assembly and using the regular one. All in Visual Studio 2013 sp4. Edited May 8, 2015 by TAz00 Process of elimination found 1 line of code Quote Link to comment Share on other sites More sharing options...
parachutingturtle Posted May 8, 2015 Share Posted May 8, 2015 (edited) hmmm, is this fix targeted at .NET 4.0 by any chance?I'm getting this in my .NET 3.5 project:warning MSB3258: The primary reference "Assembly-CSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL" could not be resolved because it has an indirect dependency on the .NET Framework assembly "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" which has a higher version "4.0.0.0" than the version "2.0.0.0" in the current target framework.and then a bunch of KSP types won't loaderror CS0246: The type or namespace name 'PartModule' could not be found (are you missing a using directive or an assembly reference?)(etc etc.)If I target .NET 4.0, it builds fine, but then KSP won't load my plugin.EDIT: recompiled the patcher for .net3.5 and it works like a charm Edited May 8, 2015 by parachutingturtle added details Quote Link to comment Share on other sites More sharing options...
sarbian Posted May 8, 2015 Author Share Posted May 8, 2015 Strange I did not have that. But I rebuilt it for 3.5 and uploaded a new version anyway. Quote Link to comment Share on other sites More sharing options...
TAz00 Posted May 8, 2015 Share Posted May 8, 2015 Seems to have fixed it. I was compiling for 4.0 Quote Link to comment Share on other sites More sharing options...
Slother Posted May 9, 2015 Share Posted May 9, 2015 I can confirm that the patch is working for me too, awesome stuff! Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.