코루틴을 배우는 과정에서 작성한 코드에 문제가 발생
게임 실행 후 유니티 엔진이 팅겨버리는 신기한 체험을 했다.
( 신기하긴 한데 두번 다시 겪고 싶지 않은 현상이었다. )
▼ 문제의 코드
public class EnemySpawner : MonoBehaviour
{
[Header("Prefab")]
[SerializeField] private GameObject enemyPrefab;
[Header("Settings")]
[SerializeField] private float spawnDelay = 1.5f;
[SerializeField] private int limit = 0;
[Header("Coordinate")]
[SerializeField] private float xMin = -5f;
[SerializeField] private float xMax = 5f;
[SerializeField] private float yPos = 0.5f;
[SerializeField] private float zPos = 11f;
private Coroutine _spawnLoop;
private void Start()
{
StartCoroutine(SpawnLoop());
}
private IEnumerator SpawnLoop()
{
int spawned = 0;
while (true)
{
if (limit > 0 && spawned >= limit)
{
yield break;
}
SpawnOne();
spawned++;
}
}
private IEnumerator SpawnOne()
{
float randomX = Random.Range(xMin, xMax);
Vector3 spawnPos = new Vector3(randomX, 0f, zPos);
Instantiate(enemyPrefab, spawnPos, Quaternion.identity);
yield return new WaitForSeconds(spawnDelay);
}
}
코루틴을 사용하여 적 스폰 루프를 만들고 싶었다.
Limit 를 설정하여 인스펙터 창에 보이게 띄우고, 인스펙터 창에서 Limit 에 값을 설정하면
그 값까지 적이 스폰되면 더이상 스폰이 안되게끔 작성했다.
그런데 게임 실행후 유니티가 팅기는 현상을 목격했다.
▼ 원인 및 해결


▼ 문제의 코드
private IEnumerator SpawnLoop()
{
int spawned = 0;
while (true)
{
if (limit > 0 && spawned >= limit)
{
yield break;
}
SpawnOne();
spawned++;
}
}
가장 큰 문제는 코루틴 체인에서 yield 가 없다는 점이었다.
- SpawnLoop( ) 안의 while ( true ) 루프는 한 번도 yield 하지 않기 때문에 한 프레임 안에서 무한 루프
- SpawnOne( )은 IEnumerator지만 , SpawnLoop()에서 그냥 함수처럼 호출만 하고 있다
└ ( SpawnOne(); ) 내부의 yield return new WaitForSeconds(spawnDelay);가 실제로 실행되지 않는다.
└ ( IEnumerator 는 StartCoroutine 이나 yield return 으로 넘겨줘야 진행된다.) - 사소하지만 yPos 를 선언해놓고 ( [SerializeField] private float yPos = 0.5f; )
└ SpawnOne( ) 함수에서 0f 로 고정해놓은 문제점도 발견
└ 이런 류의 실수는 인스펙터 값 무시 패턴으로 자주 발생한다.
즉, 코루틴 루프를 끊어주지 않아 무한 루프가 발생했고 에디터가 멈추며 팅기는 원인이 되었다.
▼수정한 코드
public class EnemySpawner : MonoBehaviour
{
[Header("Prefab")]
[SerializeField] private GameObject enemyPrefab;
[Header("Settings")]
[SerializeField] private float spawnDelay = 1.5f;
[SerializeField] private int limit = 0;
[Header("Coordinate")]
[SerializeField] private float xMin = -5f;
[SerializeField] private float xMax = 5f;
[SerializeField] private float yPos = 0.5f;
[SerializeField] private float zPos = 11f;
private void Start()
{
StartCoroutine(SpawnLoop());
}
private IEnumerator SpawnLoop()
{
int spawned = 0;
while (true)
{
if (limit > 0 && spawned >= limit)
{
yield break;
}
float randomX = Random.Range(xMin, xMax);
Vector3 spawnPos = new Vector3(randomX, 0f, zPos);
Instantiate(enemyPrefab, spawnPos, Quaternion.identity);
yield return new WaitForSeconds(spawnDelay);
spawned++;
}
}
}
- 굳이 SpawnOne( ) 이란 함수를 만들 필요가 없는것 같아 함수를 지우고
└ 함수 안에 있던 내용을 SpawnLoop( ) 에 적용 - gameObject ( Enemy ) 가 Instantiate 되고나서 Limit 값과 같아지면 yield break
- gameObject ( Enemy ) 가 Instantiate 되면 WaitForSeconds 로 1.5 초 기다린 후 다시 Instantiate 되도록 작성
- 사소하지만 상단의 private Coroutine _spawnLoop; 로 선언한 것도 필요 없는것 같아 지웠다.
코루틴 사용시 반드시 안에서 yield 로 코루틴을 끊어줘야 한다.

게임 시작 시 정상적으로 동작하는 것을 확인했다.
오늘도 또 하나를 배웠다.
'📖TIL > 🤔발생한 문제와 해결' 카테고리의 다른 글
| 팀 프로젝트 중 발생한 문제와 해결 (0) | 2025.12.16 |
|---|---|
| 팀 프로젝트 중 발생한 문제 (0) | 2025.11.11 |
| 가끔 적이 한방에 Destroy 경우 (0) | 2025.10.18 |
| 유니티 작업중 발생한 문제와 해결 (0) | 2025.10.16 |