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

游戏波次系统:如何实现间隔指定时间生成敌人?

你的波次系统延迟逻辑问题解析与修复方案

嘿,我看了你这段用来实现敌人波次生成的代码,一眼就发现了核心问题:你在普通函数里用for循环累加Time.deltaTime的方式,根本没法实现“生成下一个敌人前等待指定时长”的效果。


为啥你的代码不工作?

先给你拆解下逻辑问题:Unity的Time.deltaTime是当前帧和上一帧的时间差,而ExecuteWaveAction如果是在Update或者普通调用里执行,整个for循环会在一帧内就跑完——也就是说,timeLeftToSpawnEnemy会瞬间累加到超过action.spawnRate的值,然后一次性生成所有敌人,完全没有等待的过程。

你的原代码(片段):

void ExecuteWaveAction(WaveAction action) {
    int numberOfSpawns = spawnLocations.Length;
    int currentSpawnToInstantiate = 0;
    float timeLeftToSpawnEnemy = 0f;
    for (int i = 0; i < action.quantityOfEnemysToSpawn; i++) {
        if (timeLeftToSpawnEnemy < action.spawnRate) {
            timeLeftToSpawnEnemy += Time.deltaTime;
            i--;
        } else {
            // 实例化敌人的逻辑...
        }
    }
}

这段代码本质上是在一帧里死循环,直到timeLeftToSpawnEnemy达标,然后批量生成敌人,和你想要的“逐个间隔生成”完全不是一回事。


正确的实现方式:用Unity协程(Coroutine)

协程是Unity专门用来处理异步、延迟逻辑的工具,它能让函数暂停执行,等指定时间到了再继续跑,完美适配你的波次生成需求。下面是修改后的完整实现:

1. 把函数改成协程

// 注意返回值是IEnumerator,这是协程的标志
IEnumerator ExecuteWaveAction(WaveAction action) {
    int numberOfSpawns = spawnLocations.Length;
    int currentSpawnIndex = 0;

    // 循环生成指定数量的敌人
    for (int i = 0; i < action.quantityOfEnemysToSpawn; i++) {
        // 循环选择出生点(你也可以改成随机选,看需求)
        Transform spawnPoint = spawnLocations[currentSpawnIndex];
        currentSpawnIndex = (currentSpawnIndex + 1) % numberOfSpawns;

        // 实例化敌人(这里替换成你的敌人预制体逻辑)
        GameObject newEnemy = Instantiate(action.enemyPrefab, spawnPoint.position, spawnPoint.rotation);
        // 这里可以加敌人的初始化代码,比如设置血量、攻击值之类的

        // 如果不是最后一个敌人,就等待指定的间隔时间
        if (i != action.quantityOfEnemysToSpawn - 1) {
            yield return new WaitForSeconds(action.spawnRate);
        }
    }

    // 波次结束后可以加一些逻辑,比如通知玩家波次完成、解锁奖励等
    Debug.Log("当前波次敌人已全部生成!");
}

2. 如何启动这个协程?

不能像调用普通函数那样直接调用,得用StartCoroutine:

// 比如在波次开始的触发逻辑里调用
public void StartNextWave(WaveAction waveAction) {
    StartCoroutine(ExecuteWaveAction(waveAction));
}

额外的实用优化

  • 如果需要不受游戏时间缩放影响的精确等待(比如暂停游戏时不想继续生成敌人),可以把WaitForSeconds换成WaitForSecondsRealtime。
  • 要是需要支持中途取消波次,可以保存协程的引用,然后用StopCoroutine终止:
private Coroutine _currentWaveCoroutine;

public void StartNextWave(WaveAction waveAction) {
    // 如果有正在运行的波次,先取消
    if (_currentWaveCoroutine != null) {
        StopCoroutine(_currentWaveCoroutine);
    }
    _currentWaveCoroutine = StartCoroutine(ExecuteWaveAction(waveAction));
}

public void CancelCurrentWave() {
    if (_currentWaveCoroutine != null) {
        StopCoroutine(_currentWaveCoroutine);
        _currentWaveCoroutine = null;
        Debug.Log("当前波次已取消");
    }
}

内容的提问来源于stack exchange,提问作者Nícolas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:42:45