Unity - How to stop Play Mode in case of infinite loop? - c#

I just made a silly mistake and I ended up with an infinite loop inside my Update(). After that I wasn´t able to stop the Play Mode. Actually I wasn´t able to do anything else with Unity until I restarted it.
My question is, does anyone know how to stop the Play Mode in Unity gracefully? Is there any shortcut or some lines of code to force a timeout?
Extra Note: I have been looking for a solution to this issue for a while, unfortunately without success. However I found a solution to a side-effect of this problem. When you press ctrl-alt-del you can loose everything you haven´t save in your scene (which can be hours of work).
So Unity does an auto-save when you hit play, and the scene backup is in the Temp folder, as long as you haven´t run Unity again after a force-quit.

The following worked for me (Props to #LinusR and by extension #Kinxil) This is just a quick step-by-step.
This should work for you if you are using Visual Studio w/ Unity Tools.
Find the loop:
Open Visual Studio (if not already open)
Click Attach to Unity (if not already attached)
Click Break All (pause II symbol)
Open the Call Stack, Threads and Immediate windows. (All in Debug → Windows →)
Looking at the Call Stack, click through the threads in the Threads window.
Stop when you find the thread that the loop is on. (Call Stack helps with this)
You must be on the thread with the loop to execute necessary commands in the Immediate window.
Now get me out of here!:
[LinusR's solution seemed to be the most bullet-proof and versatile.]
Break the loop with a null value and some other options
In the Immediate window, set one of the nullable objects/fields/properties used in the loop to null e.g. for Thread.SpinWait.SpinUntil(() => someObject.NeverTrue());
someObject = null;
Unity will respond again in this instance (providing someObject remains null).
An alternative for SOME loops is simply breaking and changing the instruction or values and/or dragging the current instruction arrow (yellow arrow) out of the loop, though this may not be possible depending on the type of loop.
Think about how the loop works; How often is it executed? Will it be called each frame? etc.
Nothing working? Read the other answers here, Get creative with the Immediate window. Also in future it would be wise to have Error Pause enabled at all times in Unity.

I just got into this situation: accidental infinite loop, stuck in play mode on a scene with unsaved work, Unity unresponsive.
But I was lucky enough to have Monodevelop open, even though I was mainly using Sublime for scripting. I pressed the button to start debugging near the top left of the Monodevelop window, then hit the pause button. Execution paused on a line in the middle of my infinite loop. Windows task manager confirmed Unity was no longer locking the CPU.
In Monodevelop, I was then able to find an object obj that the next line would attempt a method call on, and use the "Immediate" window to execute obj = null. Then unpause. Unity itself now unlocks because of the null pointer error, and I could take it out of play mode and save my work.
(Unity 2017.4.1f1 Personal, Windows 10 Home x64, Monodevelop 5.9.6)
Note, I got the idea from reading #Kinxil's answer, but I had to take a slightly different approach because there was no "blocking value". I had a for (;;) loop that had previously been inside a coroutine and I changed it to be inside a FixedUpdate() without removing the loop. :\ So causing an exception was the only option I could think of.

Solution
Attach your IDE to Unity
Pause execution
Exit the loop
Optionally execute Debug.Break() to prevent the loop to enter again at the next Update()
Resume execution
Return to the Unity editor
For Visual Studio
(I haven't tested the other IDE's)
Click Attach to Unity
Wait for the process to attach (sometimes take a while)
Click Break All (pause II symbol)
Click on menu Debug → Windows → Threads
Click on the thread that contains your source code (see location column)
In your source code (text editor), move the program pointer (yellow arrow) outside the loop by dragging it to a different line in your source code.
Optionally in the case where the loop is inside some Update() event that would re-enter the loop again:
Click on menu Debug → Windows → Immediate
Type UnityEngine.Debug.Break() inside the Immediate Window and press Enter
Finally resume execution (Play button) and return to Unity editor.
Unity should now be in a "Paused" state where you can inspect what went wrong or "Stop" the Play Mode.

For me, this worked.
How To Get out of A infinite loop
Open Visual Studio.
Click "Attach to Unity" at the top (if not already clicked)
Add a breakpoint to the infinite loop by clicking the area to the left of the line number where the loop is.
You will see a yellow arrow where the breakpoint is. Click and drag this arrow to a spot outside the loop (preferably after)
Remove your current breakpoint.
Go back to unity and it will most likely take a second to unfreeze but after it unfreezes, you should be able to click the play button to stop play mode.
Boom! Panic attack averted.

It's a shame, Unreal Engine is for the most part really good at detecting infinite loops and exiting when they do, but Unity almost never seems to. It's tough to find out what's going on because Debug.Log doesn't fire until the frame completes so you can't see what's going on. A workaround to just try and see what's going on is to use some sort of limiter like this:
int limiter = 0, loopCap = 10000;
while (SomeCondition && limiter < loopCap)
{
// Do something
limiter++
}
if (limiter >= loopCap) Debug.Log("Infinite Loop avoided");
Of course, that's a much easier example because while loops can very easily become infinite loops, but if you have a ball park for where it could be happening, you could put a limiter there.
And this is only for debugging purposes so you're not having to cancel it via Task Manager. Ideally, you can find out what was the problem and remove the limiter.
I had an infinite loop a few days ago and I had no idea where it was going wrong, so I just commented out the code and then uncommented it out until it broke again, and was able to figure out where it came from.

Easily said (for MS Visual Studio):
Attach the debugger.
Add a breakpoint at a line that is called by the the infinite loop.
When the break point is reached, modify a variable to cause e.g. an null exception in consequence. You can do that in the "Locals" window (should be open when debugging; otherwise Debug/Windows/Locals or Alt+4).
Continue execution in the code editor.
Result: The Unity IDE indicates the exception and you can hit the stop-button.
Nothing else was needed in my case. Alternatively, in step 3 you might be able to change a local variable to a value that just ends the loop without an exception. But that will be only then useful, if that inifinite loop code is not called directly again afterwards.

Related

When something is highlighted in a debug console, execution just pauses until it's unhighlighted ... how do I stop this behaviour?

I start a visual studio project with debugging.
The console pops up, and I often accidently highlight something, which causes execution to pause until I unhighlight it ... I don't want it to pause ever unless I've set appropriate breakpoints.
I've tried looking around at the various options, but nothing seemed appropriate.
This superuser response answers the question.
https://superuser.com/questions/1442941/windows-10-console-stops-running-if-i-click-in-the-console-window
Basically a change in behaviour since windows 10 where QuickEdit was enabled by default, so highlighting the console would cause the console to stop printing and pause the program. By disabling QuickEdit it will not longer pause.

Force return from Native Transition in Visual Studio

I'm trying to unfreeze a program that I didn't develop and don't have the source for.
It's stuck here, I guess waiting for Windows to respond:
It won't let me move the arrow to just skip the line, and I can't change the value of eax. Is there something I can do here like force it to have an exception or somehow step into the native code further?
I just want this program to break free from its loop and start responding, so if there's some other method, that would also be a huge help.

Is there a way to run code before the debugger is paused in Visual Studio 2019/C#?

It's a wierd use case, but here's why:
I'm developing an app that uses a keyboard driver that intercepts the scan codes from attached keyboards. (https://www.oblita.com/interception.html)
The dll is being wrapped in a C# wrapper and used in my project. The problem is, whenever the debugger pauses, the key events cannot be processed (since the program is now stopped). This makes navigating while the debugger is paused very difficult. I was wondering if anyone has a clever way to deal with this. If I had some code I could run before the debugger paused at a breakpoint I could just call input.Unload() and stop the driver from intercepting.
I'm just kind of at a loss, and maybe I simply have to continue using my mouse only while the debugger is paused.
Modify your source code and insert the statement you want executed input.Unload(); on the line immediately above your breakpoint. Then when your breakpoint is hit, the code you want executed will already have been run. After you are done debugging, remove the statement.

UI behaves differently when I am debugging in Visual Studio

I have some drag and drop functionality I am using in an xceed grid. When I try to drag and item down just one row, it doesn't work. But if I put a break point in my drop method and do the drop then, it has changed when I come back to the UI. What might cause it to behave differently whether I break into the code or not?
If you "pause" your application using a debugger breakpoint, the state of the system (e.g. mouse button state) can change while it's paused, and thus be different when you allow the program to continue running. This can cause a very different behaviour than if the program were running normally. As a result of this, debugging drag and drop problems using breakpoints is often impossible.
In these situations a good approach is often to go back to basics and use a Debug.WriteLine (or similar) to dump useful information about the state of your variables as it runs "normally" (instead of killing it with a breakpoint). Then you can examine this dumped information at your leisure after the program has finished the drag, in order to work out what was happening at each stage in the process and work out why it failed.

Prevent .net ide from jumping to current executing line when breaking

When breaking in .net, it always jumps to the currently executing line. I would rather just use shortcuts to bring up the stack and go there manually if that's what I want to do.
I could have sworn I saw an option to prevent it from doing this once upon a time but I can't seem to find it anywhere now. Anyone know how to do this?
C# Keyboard layout, when I hit a breakpoint (or halt with Ctrl+Alt+PauseBreak), I usually press Ctrl+Alt+C to bring up the CallStack window, then up/down keys and press enter to navigate the call stack.
With VS2010 I've seen some weird results (options) after installing various plugins and 3rd party components at different work places...

Categories

Resources