You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 22:33:29