코루틴(Coroutine)을 사용할 때 주의해야 할 점과 발생할 수 있는 문제점들을 정리해 보았다.
StartCoroutine()으로 시작한 코루틴은 StopCoroutine() 또는 StopAllCoroutines()을 호출하지 않는 한 계속 실행된다. 특히 게임 오브젝트가 비활성화되거나 삭제되더라도, 해당 코루틴은 계속 실행될 수 있다.
해결 방법: StopCoroutine()을 사용하여 명시적으로 종료.
IEnumerator ExampleCoroutine()
{
while (true)
{
Debug.Log("Running...");
yield return new WaitForSeconds(1f);
}
}
private void OnDisable()
{
StopCoroutine(ExampleCoroutine());
}
StartCoroutine()을 여러 번 호출하면 같은 코루틴이 여러 개 실행될 수 있다. 이는 메모리 낭비와 예기치 않은 동작을 유발할 수 있다.
해결 방법: bool 플래그 사용하여 중복 실행 방지. 기존 코루틴이 실행 중이면 새로 시작하지 않도록 체크.
private Coroutine runningCoroutine;
public void StartMyCoroutine()
{
if (runningCoroutine == null)
runningCoroutine = StartCoroutine(MyCoroutine());
}
private IEnumerator MyCoroutine()
{
yield return new WaitForSeconds(5f);
runningCoroutine = null; // 실행이 끝나면 초기화
}
yield return null을 사용하면 매 프레임마다 실행됨, 따라서 불필요한 호출이 많아지면 성능 저하 발생 가능 하다.
해결 방법: WaitForSeconds() 또는 WaitForEndOfFrame()을 사용하여 실행 빈도를 조절.
IEnumerator BadCoroutine()
{
while (true)
{
// 불필요하게 매 프레임 실행
Debug.Log("Running...");
yield return null;
}
}
// 더 나은 방법: 특정 간격으로 실행
IEnumerator OptimizedCoroutine()
{
while (true)
{
Debug.Log("Running...");
yield return new WaitForSeconds(1f); // 1초마다 실행
}
}
while (true) 루프를 사용할 경우 무한 루프가 발생할 가능성이 있다.
해결방법: 루프 내에서 yield return을 항상 포함해야 한다. 특정 조건에서 break;를 사용하여 안전하게 종료.
IEnumerator SafeLoop()
{
int count = 0;
while (count < 10) // 특정 조건으로 제한
{
Debug.Log("Running: " + count);
count++;
yield return new WaitForSeconds(1f);
}
}
코루틴이 실행되는 도중에 게임 오브젝트가 삭제되면 this가 null이 되고, Unity가 예외를 발생시킬 수 있다.
해결 방법: this == null 또는 gameObject == null 체크 후 종료.
IEnumerator CheckBeforeUse()
{
while (true)
{
if (this == null) yield break; // 코루틴 안전 종료
Debug.Log("Still Running...");
yield return new WaitForSeconds(1f);
}
}
코루틴 내부에서 예외가 발생하면 Unity는 오류를 출력하지만 코루틴 자체는 종료된다.
해결 방법: try-catch 문을 사용하여 예외 처리.
IEnumerator SafeCoroutine()
{
try
{
yield return new WaitForSeconds(1f);
int result = 10 / int.Parse("0"); // 예외 발생 가능
}
catch (System.Exception e)
{
Debug.LogError("코루틴에서 예외 발생: " + e.Message);
}
}
추가)
Invoke는 특정 시간 후에 메서드를 한 번 호출하는 기능을 제공하는 Unity의 내장 함수이다.
일정 시간이 지난 후, 지정한 메서드를 한 번만 실행함.
InvokeRepeating()을 사용하면 일정 간격으로 반복 실행할 수도 있음.
using UnityEngine;
public class Example : MonoBehaviour
{
void Start()
{
// 3초 후에 "PrintMessage" 메서드 실행
Invoke("PrintMessage", 3f);
}
void PrintMessage()
{
Debug.Log("3초 후에 실행되었습니다!");
}
}
코루틴과 인보크의 차이점
결론
Invoke는 특정 시간 후에 메서드를 실행하는 간단한 기능
InvokeRepeating()을 사용하면 일정 간격으로 반복 실행 가능
CancelInvoke()로 예약된 실행을 취소할 수 있음
하지만 매개변수 전달이 불가능하고 제어가 어려우므로, 복잡한 타이밍 로직에는 Coroutine을 사용하는 것이 더 유리