Unity 코루틴 동작 원리와 사용 시 주의점
코루틴
섹션 제목: “코루틴”코루틴은 멀티 스레드처럼 병렬(parallel)로 실행되지 않고, 협력적(cooperative)으로 번갈아 실행되는 루틴이다. 일반 함수는 호출되면 끝까지 실행되고 반환하지만, 코루틴은 yield로 실행을 멈추고 나중에 멈춘 지점부터 다시 이어 간다. 진입점이 여러 개인 함수라고 볼 수 있다.
Unity의 MonoBehaviour API는 메인 스레드에서만 호출할 수 있다. 그래서 여러 프레임에 걸쳐 진행되는 작업(연출, 대기, 비동기 요청 기다리기)을 스레드 없이 메인 스레드 안에서 나눠 처리할 때 코루틴을 쓴다.
Unity에서의 동작
섹션 제목: “Unity에서의 동작”Unity에서 코루틴은 IEnumerator를 반환하고 yield를 한 번 이상 쓰는 메서드다.
- 스크립트가 코루틴 메서드를 호출해
IEnumerator객체를 만들고StartCoroutine으로 엔진에 넘긴다. - 엔진은 이 객체를 스케줄러에 보관하고, 그것을 가리키는
Coroutine객체를 호출자에게 돌려준다. - 엔진은 매 프레임 보관 중인 코루틴의
yield조건이 끝났는지 확인하고, 끝났으면MoveNext()를 호출해 다음yield까지 실행한다. - 메서드가 끝나거나,
StopCoroutine이 호출되거나, 코루틴을 시작한 게임 오브젝트가 비활성화·파괴되면 코루틴이 정리된다.
IEnumerator 인터페이스는 다음과 같다.
public interface IEnumerator{ object Current { get; } // 마지막으로 yield return한 값 bool MoveNext(); // 다음 yield까지 실행하고, 더 진행할 수 있으면 true void Reset();}엔진 없이 직접 MoveNext()를 돌리면 yield 지점마다 멈췄다가 이어지는 흐름을 확인할 수 있다. WaitForSeconds도 엔진이 해석해야 의미가 있는 객체라서, 직접 돌리면 기다리지 않고 바로 다음 값으로 넘어간다.
IEnumerator HelloWorld(){ yield return "hello"; yield return new WaitForSeconds(1.0f); yield return "world!";}
IEnumerator enumerator = HelloWorld(); // 이 시점에는 아무것도 실행되지 않는다while (enumerator.MoveNext()) // 다음 yield까지 실행하고, 값은 Current에 담긴다{ Debug.Log(enumerator.Current); // hello → WaitForSeconds 객체 → world!}Update와 비교
섹션 제목: “Update와 비교”스프라이트 알파 값을 줄이는 코드를 Update로 쓰면 매 프레임 조건을 검사한다.
public class Alpha : MonoBehaviour{ private SpriteRenderer spriteRenderer;
void Start() { spriteRenderer = GetComponent<SpriteRenderer>(); }
void Update() // 알파가 0이 된 뒤에도 매 프레임 호출된다 { Color color = spriteRenderer.color; if (color.a > 0.0f) { color.a -= 0.1f; spriteRenderer.color = color; } }}코루틴으로 쓰면 필요한 동안만 실행되고, 간격도 직접 정할 수 있다.
public class Alpha : MonoBehaviour{ private SpriteRenderer spriteRenderer;
void Start() { spriteRenderer = GetComponent<SpriteRenderer>(); StartCoroutine(FadeOut()); }
IEnumerator FadeOut() { Color color = spriteRenderer.color; while (color.a > 0.0f) { color.a -= 0.1f; spriteRenderer.color = color; yield return new WaitForSeconds(0.1f); } }}yield return의 종류
섹션 제목: “yield return의 종류”- 다음 프레임까지 대기:
null - 특정 시점까지 대기:
WaitForSeconds,WaitForFixedUpdate,WaitForEndOfFrame - 다른 작업이 끝날 때까지 대기: 다른 코루틴,
AsyncOperation,UnityWebRequest.SendWebRequest()
각 대기가 프레임의 어느 단계에서 풀리는지는 이벤트 함수의 실행 순서를 참고한다.
- 시간이나 흐름을 의도적으로 지연시킬 수 있어
Update에서 매 프레임 상태를 검사하지 않아도 된다. - 인자를 넘길 수 없는
Invoke와 달리 매개변수를 받을 수 있다. - 메인 스레드에서만 실행되므로 락이나 컨텍스트 스위칭을 신경 쓰지 않아도 된다.
제약과 주의점
섹션 제목: “제약과 주의점”- 메인 스레드에서 번갈아 실행될 뿐이라 무거운 연산을 나눠도 전체 처리 시간은 줄지 않는다. CPU를 많이 쓰는 작업은 스레드나 Job System을 검토한다.
- 코루틴을 시작한 게임 오브젝트가 비활성화되면 코루틴도 멈추고, 다시 활성화해도 이어지지 않는다. 다시 시작해야 한다.
- 이터레이터 메서드라서
ref·out매개변수를 받을 수 없다. - 한 번
MoveNext()가 호출되면 다음yield까지는 중간에 끊을 수 없다.StopCoroutine도 멈춰 있는 지점에서만 효과가 있다. yield return은catch나finally블록 안에 쓸 수 없고,catch가 있는try블록 안에도 쓸 수 없다. 익명 메서드나 람다 안에도 쓸 수 없다.StartCoroutine을 호출할 때마다 객체가 생기고,new WaitForSeconds(...)도 매번 할당된다. 자주 도는 코루틴은 같은 대기 객체를 재사용하고, 필요 없는 코루틴은 멈춰 정리한다.