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:
- 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.