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

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.


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:

  1. Open Visual Studio (if not already open)
  2. Click Attach to Unity (if not already attached)
  3. Click Break All (pause II symbol)
  4. Open the Call Stack, Threads and Immediate windows. (All in Debug → Windows →)
  5. Looking at the Call Stack, click through the threads in the Threads window.
  6. Stop when you find the thread that the loop is on. (Call Stack helps with this)
  7. 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

  1. 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).
  2. 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.
  3. 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.

Tags:

C#

Unity3D