[Unity] Coroutine

AsiaticRicecake·2025년 4월 18일

1. 📖 Coroutine

Coroutine(코루틴)은 작업을 다수의 프레임에 분산하여 처리하는 방식으로시간이 걸리는 작업을 프레임을 나눠서 처리하거나, 일정 시간 후에 무언가를 실행하고 싶을 때 사용합니다.

[SerializeField] Rigidbody rigid;
[SerializeField] float jumpPower;

private Coroutine coroutine;

private void Update()
{
  if (Input.GetKeyDown(KeyCode.G))
  {
      if (coroutine == null)
      {
          coroutine = StartCoroutine(Routine());
      }
  }

  if (Input.GetKeyDown(KeyCode.H))
  {
      if (coroutine != null)
      {
          StopCoroutine(coroutine);
          coroutine = null;
      }
  }
}

IEnumerator Routine() // 설정한 시간 만큼 대기했다가 수행하도록 만든다.
{
    Debug.Log("점프 대기");
    yield return new WaitForSeconds(1f); // 1초 대기 
    Debug.Log("점프");
    rigid.AddForce(Vector3.up * jumpPower, ForceMode.Impulse);  
}

또한 코드를 보시면 yield return을 보실 수 있는데
yield는 특정 지점에서 실행을 일시 중단하고 다시 재개할 수 있습니다!


 IEnumerator Routine()
 {
     WaitForSeconds delay = new WaitForSeconds(1f);

     Debug.Log("좀비선택 까지 5초");
     yield return delay;
     Debug.Log("좀비선택 까지 4초");
     yield return delay;
     Debug.Log("좀비선택 까지 3초");
     yield return delay;
     Debug.Log("좀비선택 까지 2초");
     yield return delay;
     Debug.Log("좀비선택 까지 1초");
     yield return delay;
     Debug.Log("또 그들이 온다...");
     coroutine = null;
 }

이렇게 카운트다운이 필요한 경우로 응용도 가능합니다.

단, 코루틴을 실행하면 클래스 객체가 생성되며 힙 메모리가 할당됩니다.
이를 해제하지 않는 상태로 반복되고 누적 될 경우, 메모리 누수가 발생할 수 있습니다.

그래서 마지막에 꼭 null로 만들어야 합니다!

coroutine = null;

또한 변수선언해 미리 할당해놓고, 해당 변수에 생성되는 코루틴 객체를 할당하는 방식을 사용한다면 메모리 공간을 절약하여 메모리 단편화를 방지할 수 있습니다.

WaitForSeconds delay = new WaitForSeconds(1f);

코루틴을 멈추고 싶으면 StopCoroutine, StopAllCoroutines 통하여 멈출 수 있습니다.

private void OnDisable()
 {
     StopCoroutine(coroutine);
     StopAllCoroutines(); // 진행중인 모든 코루틴 종료
 }

한 번에 끝내면 너무 빠르거나 끊기는 느낌을 주기 때문에
여러 프레임에 나눠 부드럽게 처리할 수 있도록 구현할 수도 있습니다.

IEnumerator MoveOverTime()
{
    for (int i = 0; i < 100; i++)
    {
        transform.position += Vector3.right * 0.1f;
        yield return null; // 다음 프레임까지 기다림
    }
}

yield return null;은 다음 프레임으로 넘어갈 때까지 실행을 일시 중지시킵니다.


어떤 조건을 걸어서 실행하도록 응용도 가능합니다.

IEnumerator WaitUntilExample()
{
    yield return new WaitUntil(() => Input.GetKeyDown(KeyCode.Space));
    Debug.Log("작업 진행하겠습니다");
}

스페이스바를 누르면 작업이 진행하도록 만들 수도 있습니다.


1-1 🔖 Coroutine 구문 정리

앞에서 여러 예시를 통해 코루틴의 함수를 살펴봤는데 한번 더 정리하겠습니다.

IEnumerator CoroutineWait()
{
  yield return null;                              
  yield return new WaitForSeconds(1f);            
  yield return new WaitForSecondsRealtime(1f);    
  yield return new WaitForFixedUpdate();          
  yield return new WaitForEndOfFrame();           
  yield return new WaitUntil(() => true);         
}

1-1-1 ✔️ yield return null;

다음 프레임까지 기다리는 구문으로 하나의 프레임을 쉬고 다음 프레임에서 다시 실행됩니다.

IEnumerator Example()
{
    Debug.Log("작업 시작");
    yield return null;
    Debug.Log("다음 프레임에서 시작");
}

즉, Update( ) 한 번 돌고 나서, 다음 프레임의 Update( ) 직전에 다시 실행됩니다.

1-1-2 ✔️ WaitForSeconds(float seconds)

게임 시간 기준으로 지정한 시간(초)만큼 기다립니다.

Time.timeScale의 영향을 받기 때문에 Time.timeScale = 0f으로 설정하면 동작하지 않습니다.

1-1-3 ✔️ WaitForSecondsRealtime(float seconds)

실제 시간 기준으로 지정한 시간(초)만큼 기다립니다.

실제 시간 기준으로 동작하여 Time.timeScale의 영향을 받지 않습니다.

이는 게임을 일시정지하는 중에 타이머가 필요한 경우 유용합니다.

1-1-4 ✔️ WaitForFixedUpdate( )

다음 FixedUpdate( ) 실행 전까지 기다립니다.

FixedUpdate( )가 보통 Rigidbody 즉, 물리연산을 처리할 때 사용합니다.
물리 연산에 맞춘 고정된 시간 간격으로 실행되는거죠

1-1-5 ✔️ WaitForEndOfFrame( )

프레임의 끝까지 기다립니다.

모든 렌더링, LateUpdate(), UI 처리가 끝난 뒤에 실행됩니다.

1-1-6 ✔️ yield return new WaitUntil(() => true);

조건을 충족하기 전까지 기다립니다.

0개의 댓글