Unity - 如何在无限循环的情况下停止播放模式?

Posted

技术标签:

【中文标题】Unity - 如何在无限循环的情况下停止播放模式?【英文标题】:Unity - How to stop Play Mode in case of infinite loop? 【发布时间】:2017-08-31 10:12:37 【问题描述】:

我只是犯了一个愚蠢的错误,在 void Update() 内部而不是写 if(var) 我写了 while(var) 并且 var 在 while 内部从未被修改过,所以我最终在我的 @ 中编写了一个无限循环987654326@

故事本身并不重要。重要的是我无法停止播放模式。实际上,在我重新启动之前,我无法使用 Unity 做任何其他事情。

所以我的问题是,有人知道如何优雅地停止 Unity 中的播放模式吗?是否有任何快捷方式或某些代码行来强制超时?

我知道最好的方法是避免无限循环,但有些东西你可能会犯一个愚蠢的错字。

额外说明:我一直在寻找解决这个问题的方法,很遗憾没有成功。但是,我找到了解决此问题的副作用的方法。当您按下 ctrl-alt-del 时,您可以释放场景中尚未保存的所有内容(这可能需要数小时的工作)。

所以当你点击播放时 Unity 会自动保存,并且场景备份在 Temp folder 中,只要你在强制退出后没有再次运行 Unity。

【问题讨论】:

你不能来自 Unity 本身。发生这种情况时,您必须从任务管理器中杀死 Unity。发布导致该问题的代码,您可能会得到答案。 感谢您的回答。实际上我自己发现了问题,正如我在问题中所说的那样,我写了一个 while() 而不是 if() 用于测试的东西我一直保持真实。 我自己从来没有用过,但是有一个(付费的)asset on the store 在这种情况下阻止 Unity。 【参考方案1】:

以下内容对我有用(@LinusR 和扩展 @Kinxil 的道具)这只是一个快速的分步。

如果您使用带有 Unity 工具的 Visual Studio,这应该适合您。

找到循环:

    打开 Visual Studio(如果尚未打开) 点击附加到 Unity(如果尚未附加) 点击Break All(暂停II符号) 打开调用堆栈线程立即窗口。 (全部在调试 → Windows →) 查看调用堆栈,点击线程窗口中的线程。 当您找到循环所在的线程时停止。 (调用堆栈对此有帮助) 您必须在带有循环的线程上才能在 立即 窗口中执行必要的命令。

现在让我离开这里!:

[LinusR 的解决方案似乎是最防弹和通用的。]

用空值和其他一些选项打破循环

    立即 窗口中,将循环中使用的可空对象/字段/属性之一设置为 null,例如对于Thread.SpinWait.SpinUntil(() => someObject.NeverTrue()); someObject = null; Unity 将在这种情况下再次响应(假设 someObject 保持为空)。 某些循环的替代方法是简单地中断和更改指令或值和/或将当前指令箭头(黄色箭头)拖出循环,但这可能无法实现,具体取决于循环类型。 想想循环是如何工作的;它多久执行一次?它会被称为每一帧吗?等 没有工作?在此处阅读其他答案,利用即时窗口发挥创意。此外,在 Unity 中始终启用 错误暂停 也是明智之举。

【讨论】:

【参考方案2】:

我刚遇到这种情况:意外无限循环,在未保存工作的场景中卡在播放模式,Unity 无响应。

但我很幸运能够打开 Monodevelop,尽管我主要使用 Sublime 编写脚本。我在 Monodevelop 窗口左上角附近按下按钮开始调试,然后按下暂停按钮。执行在我的无限循环中间的一行暂停。 Windows 任务管理器确认 Unity 不再锁定 CPU。

然后,在 Monodevelop 中,我能够找到一个对象 obj,下一行将尝试对其进行方法调用,并使用“立即”窗口执行 obj = null。然后取消暂停。由于空指针错误,Unity 本身现在已解锁,我可以将其退出播放模式并保存我的工作。

(Unity 2017.4.1f1 Personal、Windows 10 Home x64、Monodevelop 5.9.6)

注意,我从阅读@Kinxil 的答案中得到了这个想法,但我不得不采取稍微不同的方法,因为没有“阻塞值”。我有一个 for (;;) 循环,该循环以前在协程内,我将其更改为 FixedUpdate() 内而不删除循环。 :\ 所以导致异常是我能想到的唯一选择。

【讨论】:

【参考方案3】:

解决方案

    将您的 IDE 连接到 Unity 暂停执行 退出循环 可选择执行 Debug.Break() 以防止循环在下一次 Update() 时再次进入 恢复执行 返回 Unity 编辑器

对于 Visual Studio

(我还没有测试过其他 IDE)

    单击附加到 Unity 等待进程附加(有时需要一段时间) 点击全部中断(暂停II符号) 点击菜单调试 → Windows → 线程 单击包含您的源代码的线程(参见位置列) 在您的源代码(文本编辑器)中,通过将程序指针(黄色箭头)拖动到源代码中的不同行,将其移到循环之外。

可选地,如果循环位于某个 Update() 事件中,该事件将再次重新进入循环:

    点击菜单调试 → Windows → 立即 在即时窗口中输入 UnityEngine.Debug.Break() 并按 Enter

最后恢复执行(播放按钮)并返回 Unity 编辑器。 Unity 现在应该处于“暂停”状态,您可以在其中检查出了什么问题或“停止”播放模式。

【讨论】:

【参考方案4】:

对我来说,这很有效。

如何摆脱无限循环

    打开 Visual Studio。 点击顶部的“附加到 Unity”(如果尚未点击) 通过单击循环所在行号左侧的区域,向无限循环添加断点。 您会在断点所在的位置看到一个黄色箭头。单击此箭头并将其拖动到循环之外的位置(最好在之后) 删除当前断点。 回到统一状态,解冻可能需要一秒钟,但解冻后,您应该可以单击播放按钮停止播放模式。 轰隆隆!避免了惊恐发作。

【讨论】:

【参考方案5】:

很遗憾,虚幻引擎在很大程度上非常擅长检测无限循环并在它们发生时退出,但 Unity 似乎从来没有。很难找出发生了什么,因为Debug.Log 在帧完成之前不会触发,所以你看不到发生了什么。尝试查看发生了什么的解决方法是使用某种限制器,如下所示:

int limiter = 0, loopCap = 10000;

while (SomeCondition && limiter < loopCap)

    // Do something
    limiter++

if (limiter >= loopCap) Debug.Log("Infinite Loop avoided");

当然,这是一个更简单的例子,因为while 循环很容易变成无限循环,但如果你有一个可能发生的地方,你可以在那里放一个限制器。

这仅用于调试目的,因此您不必通过任务管理器取消它。理想情况下,您可以找出问题所在并移除限制器。

几天前我有一个无限循环,我不知道哪里出了问题,所以我只是注释掉了代码然后取消注释它直到它再次崩溃,并且能够弄清楚它来自哪里.

【讨论】:

以上是关于Unity - 如何在无限循环的情况下停止播放模式?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用jQuery无限循环播放音频文件

Bash:如何在按下任意键的情况下结束无限循环?

Unity的坑

unity3d 在代码中怎样控制粒子特效的重新播放与停止?答案最好详细点,可以加分

Javascript无延迟播放无限循环音频文件

unity 背景无限循环滚动效果