public Action<int> OnSpawnEvent;
// Spawn할 때
OnSpawnEvent.Invoke(1);
// DeSpawn할 때
OnSpawnEvent.Invoke(-1);
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class SpawningPool : MonoBehaviour
{
[SerializeField]
int _monsterCount = 0;
int _reserveCount = 0;
[SerializeField]
int _keepMonsterCount = 0;
[SerializeField]
Vector3 _spawnPos;
[SerializeField]
float _spawnRadius = 15.0f;
[SerializeField]
float _spawnTime = 5.0f;
public void AddMonsterCount(int value) { _monsterCount += value; }
public void SetKeepMonsterCount(int count) { _keepMonsterCount = count; }
private void Start()
{
Managers.Game.OnSpawnEvent -= AddMonsterCount;
Managers.Game.OnSpawnEvent += AddMonsterCount;
}
AddMonsterCount 함수를 액션에 추가해 주었다.
private void Update()
{
while (_monsterCount + _reserveCount < _keepMonsterCount)
{
StartCoroutine("ReserveSpawn");
}
}
현재 몬스터 수와 예약된 수가 유지해야할 몬스터 보다 적으면 코루틴을 실행시킨다.
코루틴을 통해 몬스터를 스폰하는 것이 예약이 된다.
IEnumerator ReserveSpawn()
{
_reserveCount++;
yield return new WaitForSeconds(Random.Range(0, _spawnTime));
GameObject obj = Managers.Game.Spawn(Define.WorldObject.Monster, "Knight");
NavMeshAgent nma = obj.GetOrAddCompoent<NavMeshAgent>();
Vector3 randPos;
while (true)
{
Vector3 randDir = Random.insideUnitSphere * Random.Range(0, _spawnRadius);
randDir.y = 0;
randPos = randDir + _spawnPos;
// 갈 수 있는 지역인지 체크
NavMeshPath path = new NavMeshPath();
if (nma.CalculatePath(randPos, path))
break;
}
_reserveCount--;
}
}
랜덤한 시간, 랜덤한 위치에 몬스터를 생성하는 코루틴 함수이다.
protected override void Init()
{
// Managers.Game.Spawn(Define.WorldObject.Monster, "Knight");
GameObject go = new GameObject { name = "SpawningPool" };
SpawningPool pool = go.GetOrAddCompoent<SpawningPool>();
pool.SetKeepMonsterCount(5);
}
SpawningPool이라는 게임오브젝트를 생성하고, 유지해야할 몬스터의 수를 5로 정한다.