LeeTaes 공부노트

[Unity] 코루틴(Coroutine) 본문

Game Programming/Unity Engine

[Unity] 코루틴(Coroutine)

리태s 2024. 7. 14. 12:19
728x90
반응형

코루틴(Coroutine)이란?

유니티 엔진에서 코루틴 실행을 일시 정지하고 제어를 Unity에 반환하지만 중단한 부분에서 다음 프레임을 계속할 수 있는 메서드입니다. 주로 비동기적 작업을 처리할 때 사용되며, 게임 루프의 각 프레임에서 특정 시점에 일시 중지되고 다시 시작될 수 있습니다.

 

대부분의 경우 메서드를 호출하면 실행을 완료한 뒤 호출한 메서드에 제어와 선택적 반환 값을 반환하게 됩니다. 즉, 메서드 내에서 발생한 모든 행동은 단일 프레임 업데이트 내에 발생하게 됩니다.

 

하지만 코루틴을 사용한다면 여러 프레임에 걸쳐 실행할 수 있는 코드를 작성할 수 있습니다. 유니티 Documentation에서는 HTTP 전송, 에셋 로드, 파일 I/O 완료 등을 기다리는 것과 같이 긴 비동기 작업을 처리해야 하는 경우 코루틴을 사용하는 것이 가장 좋다고 언급되어 있습니다.

코루틴의 정의와 호출

코루틴은 IEnumerator 인터페이스를 사용하여 정의됩니다. 코루틴은 yield return 구문을 사용하여 일시 중지되고, 특정 조건이 충족되면 다시 실행을 재개하게 됩니다.

 

코루틴은 메소드를 IEnumerator 타입으로 정의하고 yield return을 사용해 정의가 가능합니다.

 

예를 들어 오브젝트의 알파(불투명도)값을 다음과 같이 보이지 않을 때까지 줄이는 작업을 수행한다고 생각해보도록 하겠습니다.

 

일반적인 메서드로 작성하게 된다면 다음과 같을 것입니다.

void Start()
{
    Fade();
}

void Fade()
{
    Renderer renderer = GetComponent<Renderer>();
    
    Color c = renderer.material.color;

    for (float alpha = 1f; alpha >= 0; alpha -= 0.1f)
    {
        c.a = alpha;
        renderer.material.color = c;
    }
}

실행 결과

위 예제에서 Fade 메서드는 한 프레임 내에 수행되며, 점차 투명해지는 것이 아닌 바로 모든 for문이 순회되며 한 번에 투명하게 변경되어 화면에 출력될 것입니다.

 

이번에는 코루틴을 사용해보도록 하겠습니다.

위와 동일한 이름의 코루틴을 선언하고 시작과 동시에 실행해보도록 하겠습니다.

void Start()
{
    // 코루틴 시작
    StartCoroutine(Fade());
}

IEnumerator Fade()
{
    Renderer renderer = GetComponent<Renderer>();

    Color c = renderer.material.color;

    for (float alpha = 1f; alpha >= 0; alpha -= 0.1f)
    {
        c.a = alpha;
        renderer.material.color = c;
        yield return null;
    }
}

실행결과

이전과는 다르게 빠르지만 매 프레임마다 점점 오브젝트가 투명해지는 것을 확인할 수 있습니다.

코루틴은 위와 같이 Ienumerator 반환 타입과 바디 어딘가에 포함된 yield 반환문으로 선언하는 메서드입니다.

 

yield return null 라인은 실행이 일시 정지되고, 다음 프레임에서 다시 시작되는 지점으로, 위 예제에서는 alpha값(투명도)가 줄어들며 해당 프레임이 종료되게 됩니다.

 

즉, 1프레임마다 for문을 1차례씩 순회하며 투명도를 점차 줄여가기 때문에 위와 같이 오브젝트가 서서히 사라지는 것을 표현할 수 있게 되었습니다.

코루틴 시간 지연

기본적으로 Unity는 yield 문 다음에 프레임에 코루틴을 다시 시작하며, 위에서 사용한 null 대신 여러 키워드를 사용할 수 있습니다.

 

  • WaitForSeconds: 주어진 시간(초)만큼 대기합니다. (게임 내의 시간)
  • WaitForFixedUpdate: 다음 FixedUpdate 호출까지 대기합니다.
  • WaitForEndOfFrame: 프레임이 끝날 때까지 대기합니다.
  • WaitForSecondsRealtime:  주어진 시간(초)만큼 대기합니다. (현실 시간)

그 중 WaitForSeconds를 사용해 시간을 지연시켜보도록 하겠습니다.

// 0.2초 지연
yield return new WaitForSeconds(0.2f);

 

실행 결과

위 코드의 결과물을 보면 0.2초의 지연 시간을 추가하여 서서히 사라지는 오브젝트를 확인할 수 있습니다.

 

추가적으로 시간 지연을 활용해 게임에 걸리는 부하를 줄여줄 수도 있습니다.

예를 들어 적이 일정 거리 내에 들어오면 특정 함수를 실행해야 하는 경우가 있다고 가정해보겠습니다.

 

Update 문에서 적이 일정 거리 내에 들어올 때 특정 함수를 실행시키는 경우 적이 범위 안에 있는지 매 프레임마다 체크해야 하며, 적의 수가 늘어나는 경우 상당한 오버헤드가 발생할 수도 있습니다.

 

하지만 코루틴을 활용하여 지연 시간을 0.1초로 지정하는 경우 0.1초마다 1번만 적을 체크하기에 검사의 수를 줄일 수 있고, 결국 성능의 향상과 연결될 수 있습니다.

코루틴 정지

코루틴은 StopCoroutine(), StopAllCoroutine() 함수를 사용하여 중지할 수 있습니다. 또한 해당 오브젝트가 비활성화되면 스크립트 내의 모든 코루틴은 정지됩니다.

// Fade 코루틴 정지
StopCoroutine(Fade());
728x90
반응형