启用Timer脚本时Unity PlayMode冻结编辑器的原因分析
Unity PlayMode冻结问题排查与修复
你的脚本核心问题是难度判断的嵌套逻辑完全错误,虽然协程中的while(true)搭配yield return null不会直接造成主线程无限阻塞,但错误的逻辑会导致状态混乱,甚至引发连锁反应(比如频繁修改BlockSpawner.timeBetweenWaves导致生成逻辑异常),最终造成编辑器卡死。
逻辑错误分析
- 最外层
if(dif == 1)分支内,嵌套了if(dif == 2)和if(dif == 3)判断——这些判断永远不可能成立,因为外层已经限定了dif == 1,完全属于无效逻辑。 - 当
dif为2或3时,会进入最外层的else分支,一旦sec == 30就会强制把dif重置为1,导致难度提升逻辑完全失效,还可能引发频繁的状态切换。
修复后的代码
using System.Collections; using UnityEngine; using TMPro; public class Timer : MonoBehaviour { public TMP_Text timer; public TMP_Text DifTextpro; public float time; float sec; float min; public static float dif = 0; public string diftext; private void Start() { StartCoroutine(StopWatch()); BlockSpawner.timeBetweenWaves = Random.Range(5.2f, 6f); } IEnumerator StopWatch() { while (true) { time += Time.deltaTime; sec = (int)(time % 60); min = (int)(time / 60 % 60); timer.text = string.Format("{0:00} : {1:00}", min, sec); // 按时间顺序依次判断难度提升条件,避免嵌套逻辑混乱 if (dif == 0) { if (sec == 30) { dif = 1; diftext = "Normal"; DifTextpro.text = diftext; BlockSpawner.timeBetweenWaves = Random.Range(4f, 5.2f); } } else if (dif == 1) { if (min == 1 && sec == 15) { dif = 2; diftext = "Hard"; DifTextpro.text = diftext; BlockSpawner.timeBetweenWaves = Random.Range(3f, 4f); } } else if (dif == 2) { if (min == 2 && sec == 30) { dif = 3; diftext = "Very Hard"; DifTextpro.text = diftext; BlockSpawner.timeBetweenWaves = Random.Range(2f, 3f); } } else if (dif == 3) { if (min == 4 && sec == 15) { diftext = "Extreme"; DifTextpro.text = diftext; BlockSpawner.timeBetweenWaves = Random.Range(1.2f, 2f); } } yield return null; } } }
修复说明
- 将嵌套的
if改为顺序的else if,逻辑清晰,避免无效判断。 - 每个难度阶段只判断对应阶段的提升条件,不会出现跨阶段的错误重置。
- 移除了无用的
msec变量,简化代码。 - 改用方法名直接启动协程(
StartCoroutine(StopWatch())),避免反射调用的潜在问题。
内容的提问来源于stack exchange,提问作者DutuDev
相关产品推荐
相关产品推荐

