【问题标题】:Unity - How to stop Play Mode in case of infinite loop?Unity - 如何在无限循环的情况下停止播放模式?
【发布时间】: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。

标签: c# unity3d


【解决方案1】:

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

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

找到循环:

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

现在让我离开这里!:

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

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

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

      解决方案

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

      对于 Visual Studio

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

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

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

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

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

      【讨论】:

        【解决方案4】:

        对我来说,这很有效。

        如何摆脱无限循环

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

        【讨论】:

          【解决方案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 循环很容易变成无限循环,但如果你有一个可能发生的地方,你可以在那里放一个限制器。

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-12-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-11-27
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多