Unity ile dalga dalga düşman spawnlama

Unity ile dalga dalga düşman spawnlama

Son zamanlar da discord sunucumuz da sıkça dalga bazlı düşman spawnlama konusunda sorular geliyor. İnternette bu konuda bir çok kaynak olsada temiz kod bulmak zor olabiliyor. Bende kolları sıvadım ve geliştirmeye açık anlaşılır bir spawner sistemi hazırladım.

Spawner 3 sınıftan oluşuyor bunlar WaveSpawner, Wave ve WaveEnemy sınıfları.

Wave sınıfı dalga tanımlaması yapmamızı sağlıyor. Her dalganın kendine ait bekleme süresi var.

[System.Serializable]
public class Wave {
    public WaveEnemy[] enemies;
    public float wait;
}

WaveEnemy sınıfı her dalga içindeki farklı tiplerde düşman tanımlamamızı sağlıyor. Her düşman grubundan kaç adet ve ne kadar bekleyerek spawn olacağını belirleyebiliyoruz.

[System.Serializable]
public class WaveEnemy {
	public GameObject enemy;
	public int count;
	public float wait;
}

WaveSpawner asıl işi yapan sınıfımız. Component start fonksiyonunda bir coroutine başlatıyor. He düşman spawnlandığında onSpawn eventini çağırıyor. Her dalga tamamlandığında onComplete eventini ve tüm dalgalar tamamlandığında onWin eventini çağırıyor.


public class WaveSpawner : MonoBehaviour {

	//spawn noktaları
	public Transform[] spawnPoints;

	//düşman dalgası tanımları
	public Wave[] waves;

	//olaylar olaylar
	public UnityAction<GameObject> onSpawn;
	public UnityAction<int> onComplete;
	public UnityAction onWin;

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

	private IEnumerator spawnWave() {

		//spawnlanan düşmanların ölüp ölmediğini takip için burada tutuyoruz
		var spawnedEnemies = new List<GameObject>();

		//tanımlanan her düşman dalgası için dön
		for (var waveIndex = 0; waveIndex < waves.Length; waveIndex++) {
			var wave = waves[waveIndex];

			//her dalga başlamadan önce tanımda belirtilen süre kadar bekle
			yield return new WaitForSeconds(wave.wait);

			//düşmanları spawnla
			foreach (var waveEnemy in wave.enemies) {
				for (var i = 0; i < waveEnemy.count; i++) {

					//düşmanın kendi bekleme süresi kadar bekle
					yield return new WaitForSeconds(waveEnemy.wait);

					//spawn noktası seç
					var spawnPoint = transform;
					if (spawnPoints?.Length > 0) {
						spawnPoint = spawnPoints[Random.Range(0, spawnPoints.Length)];
					}

					//spawnlayıp listemize ekle
					var go = Instantiate(waveEnemy.enemy, spawnPoint.position, spawnPoint.rotation);
					spawnedEnemies.Add(go);
					if (onSpawn != null) onSpawn(go);

				}
			}

            //yazıdaki odak noktam spawner olduğu için düşman scriptinden izole 
            //olması için ölme kontrolünü burda yaptım ama siz kendi düşman 
            //scriptiniz ile bu kısma ihtiyaç olmadan kodu daha da kısaltabilirsiniz.
            foreach (var enemy in spawnedEnemies) {
					
				//düşman ölene kadar bekle
				while (enemy) {
					yield return null;
				}

			}

			//dalga tamamlandı bütün düşmanlar pert
			spawnedEnemies.Clear();
			if (onComplete != null) onComplete(waveIndex);

		}

		//kazandı
		if (onWin != null) onWin();

	}

}

Örnek kullanım.

public class Test : MonoBehaviour {

    public Text log;

    private void Start() {
        var spawner = GetComponent<WaveSpawner>();
        spawner.onComplete += i => log.text = (i + 1) + ". dalga tamamlandı";
        spawner.onWin += () => log.text = "Kazandın";
    }

}
Yorumlar