Coroutine

코루틴이란, 동시 실행 루틴이라고 불리며 쓰레드의 개념을 이해한다면 쉽게 파악할 수 있다.

간단하게 설명하자면 Update함수의 경우 게임 로직의 가장 중요한 부분이며 프레임 단위로 이루어지기 때문에 매우 빠른 속도로 동작한다.

이 때, 동작하는 함수들 중 어느정도 딜레이가 필요한 함수가 있다면 해당 함수를 time을 사용하여 지연시키는 방법도 있지만 해당 프로그램의 전체적인 지연보다 한가지 쓰레드를 추가로 사용하여 서브루틴을 구성할 수 있다.

time의 방식의 경우 딜레이 만큼 프로그램이 정지하기 때문에 다른 행동을 하지 못하거나 Update자체의 덩치가 커질 우려가 있기 때문에 서브 루틴을 만들어 구성한다면 전체적인 폼을 건들지 않고 딜레이가 가능하다.

추가로 프레임 드랍과 Update함수에 종속되지 않음

다시 말해 서브루틴을 생성할 수 있는 기능이 바로 코루틴 함수이다.

유니티 상에서는 따로 코루틴함수를 쉽게 구현할 수 있도록 구조화되어 있어서 간단하게 사용가능하나 사용하기 전 내부의 동작과정이해가 필수적이라고 생각한다.

실습

public class coroutine : MonoBehaviour
{
    public float speed = 2.0f;

    private void Start()
    {
        StartCoroutine(right_move());
    }

    IEnumerator right_move()
    {
        while (transform.position.x < 10f)
        {
            transform.Translate(transform.right * Time.deltaTime * speed);
            yield return new WaitForSeconds(0.1f);
        }
    }
}

위의 스크립트는 기본적인 코루틴의 예이다.

해당 스크립트가 컴포넌트에 부착된 게임오브젝트는 x축이 월드좌표로 10f보다 작다면 천천히 x축으로 이동하게 된다.

보다시피 Update에서 벗어나서 독립적인 실행 형태를 보인다.

코루틴 함수는 Start이전에 실행하거나 비활성화인 오브젝트에서 정상적으로 동작하지 않는다.

StartCoroutine

유니티상에서 코루틴을 실행시키는 함수이다.

위 처럼 함수의 원형을 적는 방법과 합수의 이름을 문자열로 기입할 수 있다.

하지만 문자열로 기입하는 경우 비용이 매우 비싸지니 원형기입을 사용하자..!

  • 박싱과 언박싱과정에서 오버헤드를 일으킬 수 있으며 함수의 원형을 변경시 오류가 표시되지 않을 수 있음

StartCoroutine(코루틴원형());

IEnumerator

코루틴함수의 리턴값이 IEnumerator형태인 것을 확인할 수 있으며 내부에선 yield return을 하고 있는 모습이다.

C#에서 콜렉션 인터페이스는 IEnumerator상속받아 구현된다.

데이터를 리턴하는 열거자로 내부에는 기본적으로 구현해야하는 원형이 있다.

  • Current 현재위치의 데이터를 반환하는 프로퍼티
  • MoveNext다음 위치로 이동하며 데이터의 유무에 따라 참과 거짓을 리턴하는 함수
  • Reset초기위치로 돌리는 함수(-1)

이러한 구조로 코루틴 내부에서도 이러한 형태로 반환값이 연속적으로 이루어진다.

유니티상에서는 매우 중요한 부부은 아니지만 내부가 궁금하다면 검색추천..!

yield

코루틴함수를 만들기 위해서 IEnumerator반환형식으로 함수를 만들게 되면 처음 빨간줄이 생긴다.

이는 yield return형식을 작성하지 않아서 일부값만 반환하는다는 오류가 뜨는 것!

따라서 최소한 하나의 yield문이 존재해야 한다.

  • yield null: 한프레임동안 제어권을 넘겨준뒤 재개한다.
  • yield return new WaitForSeconds: 넘겨준 인자만큼의 초를 대기후 재개한다.
  • yiedl return new WaitForSecondsRealtime: 타임스케일의 영향을 받지않고 넘겨준 인자만큼 대기 후 재개한다.
  • yield return new WaitForFixedUpdate: 모든 스크립트에서 FixedUpdate업데이트가 호출된 뒤 재개한다.
  • yield return new WaitForEndOfFrame: 랜더링을 완료한 뒤 프레임을 표시하기 전에 호출
  • yield return StartCoroutine(): 코루틴을 실행한 뒤 코루틴이 완료된 뒤에 실행

yield return은 코드의 제어권을 유니티엔진에 넘겨주고 뒤에 붙는 조건에 따라 다시 코드를 실행한다.

  • yield break: 해당 코드에서 코루틴이 종료됨

StopCoroutine

만약 코루틴을 사용하여 서브루프(추가 Update문)를 만든다고 가정한다면 해당 코루틴의 동작을 정지하기 위해선 StopCoroutine명령어를 통해 정지시켜야 한다.

앞서 배운 IEnumerator의 값을 반환하여 넘겨주는 StartCoroutine(코루틴());의 방식과 같이 해당 코루틴은 함수포인터와 유사하게 작동하기 때문에 StopCoroutine(코루틴())과 다른 코루틴함수이다.

따라서 해당 코루틴을 멈추기 위해선 같은 IEnumerator변수를 사용하여 관리해야한다.

{
    public float speed = 2.0f;
    IEnumerator enumerator;

    private void Start()
    {
        enumerator = right_move();
        StartCoroutine(enumerator);
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            StopCoroutine(enumerator);
        }
    }

    IEnumerator right_move()
    {
        while (true)
        {
            transform.Translate(transform.right * Time.deltaTime * speed);
            yield return new WaitForSeconds(0.1f);
        }
    }
}

앞서 사용한 문자열로 해당 코루틴을 실행시키고 종료시키는 것은 가능하나, 실행중인 코루틴이 여러개일 경우 동시적으로 멈춰버리게 된다.

++ StopAllCoroutine

이 함수는 컴포넌트가 가지고 있는 모든 코루틴 함수를 종료 시킨다.

코루틴 함수 매개변수

코루틴함수또한 매개변수를 전달할 수 있다.

public class coroutine : MonoBehaviour
{
    public float speed = 2.0f;

    private void Start()
    {
        StartCoroutine(right_move(10));
    }

    IEnumerator right_move(int max_x)
    {
        while (max_x > transform.position.x)
        {
            transform.Translate(transform.right * Time.deltaTime * speed);
            yield return new WaitForSeconds(0.1f);
        }
    }
}

태그: ,

카테고리:

업데이트:

댓글남기기