简体   繁体   English

敌人波产卵者统一

[英]Enemy wave spawner in unity

I'm trying to create a wave spawner for a top down game that I'm creating. 我正在尝试为自己创建的自上而下游戏创建wave生成器。 I have created the wave spawner script but when I hit play, nothing happens. 我已经创建了wave生成器脚本,但是当我点击play时,什么也没有发生。 The countdown doesn't begin. 倒计时不会开始。 Ideally it should start from 2, once it reaches 0, the first wave should spawn with one enemy. 理想情况下,它应从2开始,一旦达到0,则第一波应与一个敌人一起产生。 Once that enemy is killed, the countdown should begin from 5 and once 0 is reached, the next wave with 2 enemies should begin and so on. 一旦该敌人被杀死,倒数应从5开始,一旦达到0,则下一个有2个敌人的波浪应开始,依此类推。 The new wave should not begin until all the current enemies are destroyed. 在所有当前敌人被消灭之前,新一波浪潮不应开始。

public enum SpawnState { SPAWNING, WAITING, COUNTING };

public SpawnState state = SpawnState.COUNTING;

public Transform enemy;

public float timeBetweenWaves = 5f;
public float countDown = 2f;

private int waveIndex = 0;

public float searchCountdown = 1f;   

void Update()
{        
  if (state == SpawnState.WAITING)
  {           
    if (!EnemyisAlive())
       {
          WaveCompleted();
        }
        else
        {                
            return;
        }
    }

  if (countDown <= 0f)
  {          
      if (state != SpawnState.SPAWNING)
      {              
          StartCoroutine(SpawnWave());
          countDown = timeBetweenWaves;
      }
      else
      {              
          countDown -= Time.deltaTime;
      }

  }

}

void WaveCompleted()
{        
    state = SpawnState.COUNTING;
    countDown = timeBetweenWaves;
    SpawnWave();        
}

bool EnemyisAlive()
{        
    searchCountdown -= Time.deltaTime;
    if (searchCountdown <= 0)
    {
        searchCountdown = 1f;
        if (GameObject.FindGameObjectsWithTag("Enemy").Length == 0)
        {
            return false;
        }
    }
    return true;
 }

IEnumerator SpawnWave()
 {        
    state = SpawnState.SPAWNING;
    waveIndex++;
    for (int i = 0; i < waveIndex; i++)
    {
        SpawnEnemy();
        yield return new WaitForSeconds(0.5f);

    }
    state = SpawnState.WAITING;
    yield break;
 }

void SpawnEnemy()
 {
    Instantiate(enemy, transform.position, transform.rotation);
 }   

I would recommend you to use a Coroutine for all of it. 我建议您对所有程序都使用协程。 That makes some things easier. 这使某些事情变得容易。 You can eg simply wait until another Ienumertaor is finished. 例如,您可以简单地等到另一个Ienumertaor完成。 Then I would simply add the spawned enemies to a list, filter it for null entries and use the count. 然后,我只需将生成的敌人添加到列表中,将其过滤为null条目并使用计数。 Using Find or in your case FindGameObjectsWithTag each frame is highly inefficient! 使用Find或您的情况下的FindGameObjectsWithTag每个框架的效率都非常低!

using System.Linq;
using System.Collections.Generic;

...

public Transform enemy;

public float timeBetweenWaves = 5f;
public float countDown = 2f;

//public float searchCountdown = 1f; 

private List<Transform> enemies = new List<Transform>();
private int waveIndex = 0;

private void Start()
{
    StartCoroutine(RunSpawner());
}

// this replaces your Update method
private IEnumerator RunSpawner()
{        
    // first time wait 2 seconds
    yield return new WaitForSeconds(countDown);

    // run this routine infinite
    while(true)
    {
        state = SpawnState.SPAWNING;    

        // do the spawning and at the same time wait until it's finished
        yield return SpawnWave();

        state = SpawnState.WAITING;

        // wait until all enemies died (are destroyed)
        yield return new WaitWhile(EnemyisAlive);

        state = SpawnState.COUNTING

        // wait 5 seconds
        yield return new WaitForSeconds(timeBetweenWaves);
    }
}

private bool EnemyisAlive()
{        
    // uses Linq to filter out null (previously detroyed) entries
    enemies = enemies.Where(e => e != null).ToList();

    return enemies.Count > 0;
}

private IEnumerator SpawnWave()
{        
    waveIndex++;
    for (int i = 0; i < waveIndex; i++)
    {
        SpawnEnemy();
        yield return new WaitForSeconds(0.5f);
    }
}

private void SpawnEnemy()
{
    enemies.Add(Instantiate(enemy, transform.position, transform.rotation));
}

To be slightly more efficient you could also avoid instantiating and destroying but rather use Object Pooling - only enabling and disabling the objects and eventually spawn new ones only when needed. 为了稍微提高效率,您还可以避免实例化和销毁,而应使用对象池 -仅启用和禁用对象,并最终仅在需要时才产生新对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM