89 lines
5.6 KiB
C#
89 lines
5.6 KiB
C#
using UnityEngine; // 유니티 기능을 불러올거에요 -> UnityEngine을
|
|
using System.Collections; // 코루틴을 사용할거에요 -> System.Collections를
|
|
using System.Collections.Generic; // 리스트를 사용할거에요 -> System.Collections.Generic을
|
|
|
|
public class MonsterSpwaner : MonoBehaviour // 클래스를 선언할거에요 -> 몬스터 스포너를
|
|
{
|
|
[Header("스폰 설정")]
|
|
[SerializeField] private List<GameObject> monsterPrefabs; // 리스트를 선언할거에요 -> 스폰할 몬스터 프리팹들을
|
|
[SerializeField] private List<Transform> spawnPoints; // 리스트를 선언할거에요 -> 스폰 위치들을
|
|
|
|
[Tooltip("이 스포너에서 동시에 유지할 최대 몬스터 수")]
|
|
[SerializeField] private int maxMonsters = 5; // 변수를 선언할거에요 -> 이 스포너가 유지할 최대 마릿수를
|
|
|
|
[Tooltip("몬스터가 죽은 뒤 몇 초 후에 다시 스폰할지")]
|
|
[SerializeField] private float respawnDelay = 5f; // 변수를 선언할거에요 -> 죽고 나서 재스폰까지 대기 시간을
|
|
|
|
// 이 스포너가 관리하는 몬스터 목록
|
|
// null이면 → 죽어서 비어있는 슬롯 (재스폰 대상)
|
|
private List<GameObject> _managedMonsters; // 리스트를 선언할거에요 -> 슬롯별 몬스터 오브젝트를
|
|
|
|
// ─────────────────────────────────────────────────────────
|
|
|
|
private void Start() // 함수를 실행할거에요 -> 시작 시
|
|
{
|
|
// 슬롯 리스트를 maxMonsters 크기로 초기화 (전부 null = 비어있음)
|
|
_managedMonsters = new List<GameObject>(); // 초기화할거에요 -> 슬롯 목록을
|
|
for (int i = 0; i < maxMonsters; i++) // 반복할거에요 -> 최대 마릿수만큼
|
|
{
|
|
_managedMonsters.Add(null); // 추가할거에요 -> 빈 슬롯을
|
|
}
|
|
|
|
// 처음에 모든 슬롯 즉시 스폰
|
|
for (int i = 0; i < maxMonsters; i++) // 반복할거에요 -> 슬롯마다
|
|
{
|
|
SpawnAtSlot(i); // 실행할거에요 -> 즉시 스폰을
|
|
}
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────
|
|
// 매 프레임 슬롯 감시
|
|
// ─────────────────────────────────────────────────────────
|
|
|
|
private void Update() // 함수를 실행할거에요 -> 매 프레임
|
|
{
|
|
for (int i = 0; i < _managedMonsters.Count; i++) // 반복할거에요 -> 모든 슬롯을
|
|
{
|
|
GameObject mob = _managedMonsters[i]; // 가져올거에요 -> 슬롯의 몬스터를
|
|
|
|
// 슬롯이 비어있거나(null), 오브젝트가 비활성화됐으면 → 죽은 것으로 판단
|
|
if (mob == null || !mob.activeInHierarchy) // 조건이 맞으면 실행할거에요 -> 슬롯이 비었으면
|
|
{
|
|
_managedMonsters[i] = null; // 초기화할거에요 -> 슬롯을 명확하게 null로
|
|
StartCoroutine(RespawnAfterDelay(i)); // 시작할거에요 -> 재스폰 대기 코루틴을
|
|
_managedMonsters[i] = new GameObject("RespawnPending"); // 임시 표시할거에요 -> 중복 코루틴 방지용으로
|
|
// 실제 스폰은 RespawnAfterDelay에서 처리
|
|
}
|
|
}
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────
|
|
// 재스폰 대기 코루틴
|
|
// ─────────────────────────────────────────────────────────
|
|
|
|
private IEnumerator RespawnAfterDelay(int slotIndex) // 코루틴을 정의할거에요 -> n초 대기 후 재스폰을
|
|
{
|
|
yield return new WaitForSeconds(respawnDelay); // 기다릴거에요 -> 설정한 대기 시간만큼
|
|
SpawnAtSlot(slotIndex); // 실행할거에요 -> 해당 슬롯에 스폰을
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────
|
|
// 실제 스폰
|
|
// ─────────────────────────────────────────────────────────
|
|
|
|
private void SpawnAtSlot(int slotIndex) // 함수를 선언할거에요 -> 특정 슬롯에 몬스터를 스폰하는
|
|
{
|
|
if (monsterPrefabs.Count == 0 || spawnPoints.Count == 0) return; // 중단할거에요 -> 설정이 없으면
|
|
|
|
// 랜덤 프리팹, 랜덤 스폰 위치 선택
|
|
GameObject prefab = monsterPrefabs[Random.Range(0, monsterPrefabs.Count)]; // 뽑을거에요 -> 랜덤 몬스터 프리팹을
|
|
Transform point = spawnPoints[Random.Range(0, spawnPoints.Count)]; // 뽑을거에요 -> 랜덤 스폰 위치를
|
|
|
|
GameObject mob = Instantiate(prefab, point.position, point.rotation); // 생성할거에요 -> 몬스터를
|
|
// OnEnable() → ResetStats() 자동 호출되므로 별도 초기화 불필요
|
|
|
|
_managedMonsters[slotIndex] = mob; // 저장할거에요 -> 슬롯에 몬스터 오브젝트를
|
|
|
|
Debug.Log($"[Spawner] 슬롯 {slotIndex} 스폰 완료: {mob.name}"); // 로그를 찍을거에요
|
|
}
|
|
} |