코루틴

최정훈·2024년 10월 5일

유니티 공식문서 발췌
코루틴을 사용하면 작업을 다수의 프레임에 분산할 수 있습니다. Unity에서 코루틴은 실행을 일시정지하고 제어를 Unity에 반환하지만 중단된 부분에서 다음 프레임을 계속할 수 있는 메서드입니다.

  • 게임 오브젝트의 알파값을 점점 낮추기 위해서 다음과 같은 함수를 작성했다고 가정해보자 .

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

    하지만, 이는 의도한대로 작동하지 않을 것이다. 하나의 프레임 업데이트에서 전체적으로 실행이 되어버리기 때문에, 화면에는 아무것도 보이지 않을 것이다.(실행과 동시에 알파값이 0으로 변경되기 때문에)

  • 원하는 효과를 내기 위해서 Update()문에서 이 함수를 호출한다면, 물론 작동할 것이다. 하지만, 또 다른 효과들을 추가하고 싶을 때, 계속 이와 같은 방식으로 추가하여 여러 조건들을 조건문으로 처리한다는 것은 유지보수 측면에서 비효율적일 것이다. 이를 해결하기 위해서 Coroutine을 사용한다. 다음과 같이 IEunmerator를 반환값으로 가지며 yield로 구성되어 있다.

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

    위에서 yield부분을 만나게 되면, 유니티가 단일 스레드 방식으로 작동함에도 불구하고, 다른 루틴에게 수행권한을 넘겨서 마치 여러개의 쓰레드가 동시에 동작하는 것(멀티 스레드)과 같은 효과를 제공한다.

    중요한 개념이기 때문에 다시 한번 강조하자면, 멀티 쓰레드(비동기적 실행)처럼 보이지만, 실제는 싱글 스레드에서 작동하는 것.

  • 아래 사진에서 볼 수 있듯이, 코루틴은 Update와 같은 부분에 존재하며 yield를 통해 Update와 루틴을 번갈아서 실행한다.

    yield를 반환하는 시점, 양보하는 시점을 프로그래머가 조절할 수 있기 때문에, 원하는 시점에 코드를 실행하고 종료할 수 있다.


  • 하지만, 단점도 존재한다. 코루틴을 사용할 때 주로,

    yield new WaitForSeconds();

    와 같이 new를 통해 새로운 인스턴스를 생성하게 되는데 이는 가비지를 생성하게 된다.

    코루틴을 사용하면 손해인 경우도 존재한다. 만약 몬스터를 구현하는데 있어서, 특정 행동을 코루틴으로 구현했다고 가정하자. 몬스턴가 10마리 정도만 있다면 문제될 것이 없다.

    하지만, 뱀서류 게임같이 몬스터가 끝도 없이 나오는 게임같은 경우, 이러한 방식은 심각한 프레임 드랍을 유발할 수 있다.


  • yield에서 사용할 수 있는 구문들

    yield return new WaitForSecondsRealtime (float time)기본적으로 WaitForSecond()와 동일하지만, timeScale의 영향을 피할 수 있다.
    yield return new WaitForFixedUpdate ()다음 FixedUpdate()가 실행될 때까지 대기
    yield return new WaitForEndOfFrame ()하나의 프레임이 완전히 종료될 때까지 대기. Update(), LateUpdate(), 이벤트까지 모두 호출된 후 호출
    yield return null다음 Update()까지 대기
    yield return new WaitUntil (System.Func<Bool> predicate)특정 조건식이 성공할때까지 대기
    yield return new WaitWhile(System.Func<Bool> predicate)특정 조건식이 true인동안 대기
    yield return StartCoroutine (IEnumerator coroutine)내부에서 코루틴을 호출하고, 완료될 때까지 대기

  • 코루틴 정지

    public void StopCoroutine(IEnumerator routine)StartCoroutine에서 사용한 코루틴 함수의 열거자를 사용하여 중단
    public void StopCoroutine(string methodName)매개변수를 문자열로 전달하여 중단
    public void StopAllCoroutines()현재 클래스에서 사용되고 있는 모든 코루틴을 중단

- 코루틴에서 GC가 호출되는 경우 1. StartCoroutine 매서드를 실행하는 순간 유니티는 해당 코루틴을 관리하기 위해서 엔진 내부에 인스턴스를 생성하는데, 이는 추후에 GC를 호출한다. 2. yield 위에서도 언급했지만, 주로 new를 통해서 새로운 인스턴스를 할당하기 때문에, 추후에 GC를 호출한다. 이는 yield구문을 캐싱하여 해결할 수 있다. ```csharp vat waitCache = new WaitForSeconds(1f); yield return waitCache; ```
profile
게임개발자(희망)의 공부일지

0개의 댓글