Unity中GameManager单例timeOver为true时仍触发Cube生成的问题
问题:Unity中Cube生成脚本无视GameManager单例的timeOver状态始终执行生成逻辑
我的实现代码
GameManager单例脚本
public static GameManager instance; public float score; public float amoutOfBullets; public int timeLeft; public bool timeOver = true; private void Awake() { if (instance == null) instance = this; }
Cube生成脚本
public List<GameObject> spawnedCubes = new List<GameObject>(); public GameObject Cube; bool spawned = false; void Update() { Debug.Log(GameManager.instance.timeOver + " at the start of spawning"); if (GameManager.instance.timeOver == false) { if (spawned == false) { spawned = true; StartCoroutine(Delay()); } else { DestroyAllCubes(); } } } IEnumerator Delay() { Vector3 randomSpawnPosition = new Vector3(Random.Range(-10, 11), (Random.Range(0.5f, 13)), (Random.Range(20, 100))); GameObject newCube = Instantiate(Cube, randomSpawnPosition, Quaternion.identity); spawnedCubes.Add(newCube); yield return new WaitForSeconds(2); spawned = false; } //go through the list with spawnded cubes and destroy them after time is over void DestroyAllCubes() { foreach (GameObject cube in spawnedCubes) { Destroy(cube); } spawnedCubes.Clear(); }
问题现象
尽管GameManager单例中timeOver初始值设为true,但Cube生成脚本仍会执行生成逻辑,无视Update方法中的判断条件if (GameManager.instance.timeOver == false),无论timeOver状态如何,生成操作总会触发。
解决方案
1. 修复单例的唯一性问题
当前单例实现存在漏洞:如果场景中有多个GameManager对象,或者切换场景时未处理单例持久化,会导致instance被覆盖或出现多实例干扰状态。修改Awake方法确保单例唯一且跨场景保留:
private void Awake() { if (instance == null) { instance = this; DontDestroyOnLoad(gameObject); // 保持单例跨场景存在 } else { Destroy(gameObject); // 销毁重复生成的实例 } }
2. 给协程增加状态检查
协程启动后会独立运行到完成,即使timeOver中途变为true,原代码里的Instantiate还是会执行。需要在协程中加入状态判断:
IEnumerator Delay() { // 启动生成前先检查状态,不符合则终止协程 if (GameManager.instance.timeOver) { spawned = false; yield break; } Vector3 randomSpawnPosition = new Vector3(Random.Range(-10, 11), (Random.Range(0.5f, 13)), (Random.Range(20, 100))); GameObject newCube = Instantiate(Cube, randomSpawnPosition, Quaternion.identity); spawnedCubes.Add(newCube); yield return new WaitForSeconds(2); // 等待结束后再次检查状态,避免错误重置标记 if (!GameManager.instance.timeOver) { spawned = false; } }
3. 修正Update中的逻辑分支
原代码在timeOver == false的分支里处理销毁Cube,会导致刚生成的Cube立刻被销毁。调整逻辑,把销毁操作放到timeOver == true的分支中:
void Update() { Debug.Log(GameManager.instance.timeOver + " at the start of spawning"); if (GameManager.instance.timeOver) { // 时间结束时销毁所有Cube if (spawnedCubes.Count > 0) { DestroyAllCubes(); } spawned = false; // 重置生成标记,避免下次启动时状态异常 } else { // 时间未结束时生成Cube if (!spawned) { spawned = true; StartCoroutine(Delay()); } } }
4. 追踪timeOver的状态变化
检查是否有其他脚本错误修改了timeOver的值,可通过属性封装来监控状态变化:
private bool _timeOver = true; public bool timeOver { get => _timeOver; set { Debug.Log($"timeOver状态变更:{_timeOver} → {value}"); _timeOver = value; } }
通过日志输出就能清晰看到timeOver的修改记录,排查异常赋值的情况。
内容的提问来源于stack exchange,提问作者NewbieProgrammer
相关产品推荐
相关产品推荐

