【问题标题】:Enemy wave spawner in unity统一的敌人波生成器
【发布时间】:2019-06-26 00:26:31
【问题描述】:

我正在尝试为我正在创建的自上而下的游戏创建波浪生成器。我已经创建了 wave spawner 脚本,但是当我点击播放时,什么也没有发生。倒计时没有开始。理想情况下,它应该从 2 开始,一旦达到 0,第一波应该与一个敌人一起生成。一旦该敌人被杀死,倒计时应从 5 开始,一旦达到 0,则应开始下一波有 2 个敌人的波,依此类推。在所有当前敌人被消灭之前,新一波不应开始。

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);
 }   

【问题讨论】:

  • derHugo 已经为您提供了一个可靠的答案,但是关于为什么什么都没发生的 TLDR:state 被初始化为 SpawnState.COUNTING 和 countDown 被初始化为 2f 所以除非您进行一些调整对于检查器中的序列化值,Update() 中的 if 条件都不是真的。
  • 另外,您的 WAITING 状态实际上永远不会等待。如果状态为 not SPAWNING,则将状态设置为 SPAWNING 并生成。
  • Foggzie 和 Draco18s - 感谢您的帮助...我对脚本进行了更改,现在它可以正常工作了。

标签: c# unity3d


【解决方案1】:

我建议您使用协程来完成所有这些工作。这使一些事情变得更容易。你可以例如只需等到另一个 Ienumertaor 完成。然后我只需将生成的敌人添加到列表中,过滤它以查找null 条目并使用计数。使用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));
}

为了稍微提高效率,您还可以避免实例化和销毁,而是使用Object Pooling - 仅在需要时启用和禁用对象并最终生成新对象。

【讨论】:

    猜你喜欢
    • 2023-02-09
    • 1970-01-01
    • 1970-01-01
    • 2013-05-21
    • 2016-07-14
    • 1970-01-01
    • 2013-03-10
    • 2017-10-04
    • 1970-01-01
    相关资源
    最近更新 更多