等待特定的秒数来产生敌人

时间:2018-03-21 13:30:32

标签: c# unity3d timer

所以......我正在为这个Wave系统工作一个小游戏,我希望系统在产生另一个敌人之前等待一段特定的时间,所以我做了这件事:

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
        {
            GameObject.Instantiate (action.enemyToSpawn, spawnLocations [currentSpawnToInstantiate].position, Quaternion.identity);
            currentSpawnToInstantiate++;

            timeLeftToSpawnEnemy = 0f;

            if (currentSpawnToInstantiate >= numberOfSpawns)
                currentSpawnToInstantiate = 0;
        }
    }
}

如果你问自己WaveAction是什么:

public struct WaveAction
{
    public int quantityOfEnemysToSpawn;
    public float spawnRate;
    public GameObject enemyToSpawn;
}

我不知道代码有什么问题,当我调试一切似乎没问题时,脚本实际上会在产生之前等待,但是当我正在播放脚本时会立即产生所有生物。

如果有人可以帮助我,我将非常感激,最后,如果我犯了任何拼写错误或英语错误,我很抱歉,我不是母语为英语的人

2 个答案:

答案 0 :(得分:2)

我建议使用协程:

IEnumerator ExecuteWaveAction(WaveAction action) {
    int currentSpawnToInstantiate = 0;
    for (int i = 0; i < action.quantityOfEnemysToSpawn; i++) 
    {
            // spawn object
            GameObject.Instantiate (action.enemyToSpawn, spawnLocations [currentSpawnToInstantiate].position, Quaternion.identity);
            currentSpawnToInstantiate++;
            if (currentSpawnToInstantiate >= numberOfSpawns)
                currentSpawnToInstantiate = 0;

            // waits for 1 sec before continue. you can change the time value
            yield return new WaitForSeconds(1);
        }
    }

答案 1 :(得分:1)

首先让我们看看Time.deltaTime

  

完成最后一帧所花费的时间(只读)。

     

使用此功能可以使您的游戏帧速率独立。

在Unity中,无论何时需要制定与时间相关的场景,您都必须使用协同例程,否则它完全取决于您的代码逻辑来衡量增量时间。

在一个简单的协同程序中,我们将逻辑包装在循环中,并且我们有一个yield语句,该值表示协程在每次传递后应该等待的时间(帧)。

UpdateFixedUpdate方法是Unity内置协同程序,分别每Time.deltaTimeTime.fixedDeltaTime秒执行一次。

由于ExecuteWaveAction必须使用增量时间,因此产卵的逻辑必须具有协程才能正常工作。

int numberOfSpawns = spawnLocations.Length;
int currentSpawnToInstantiate = 0;
float timeLeftToSpawnEnemy = 0f;
WaveAction action = set this in advance;

void Start()
{
    action = ... 
    ExecuteWaveAction(); 
}

void ExecuteWaveAction()
{
    numberOfSpawns = spawnLocations.Length;
    currentSpawnToInstantiate = 0;
    timeLeftToSpawnEnemy = 0f;
    i = 0;    
}

现在看一下循环逻辑如何与原始方法分离并放入协程:

int i = 0;
void Update()
{
    //if spawning is active then continue...
    if (i < action.quantityOfEnemysToSpawn) 
    {
        if (timeLeftToSpawnEnemy < action.spawnRate) 
        {
            timeLeftToSpawnEnemy += Time.deltaTime;
        }
        else
        {
            i++;

            GameObject.Instantiate (action.enemyToSpawn, spawnLocations [currentSpawnToInstantiate].position, Quaternion.identity);
            currentSpawnToInstantiate++;

            timeLeftToSpawnEnemy = 0f;

            if (currentSpawnToInstantiate >= numberOfSpawns)
                currentSpawnToInstantiate = 0;
        }
    }
}

注意:

您可能想知道为什么我们不能在循环中使用Time.deltaTime?

答案是:因为Time.deltaTime表示一帧的时间长度(基本上等于同一Update方法的每两次连续执行之间的延迟),但是一个简单的循环一次全部运行框架,因此Time.deltaTime只告诉我们一些其他延迟,我们的循环不会在它上面工作。

换句话说,Unity不会在循环内等待一个帧结束,但它会在执行每个协同程序后等待(等待时间=帧长度(即Time.deltaTime或Time.fixedDeltaTime或手动协程等待时间)。