Home Coroutine
Post
Cancel

Coroutine

Coroutine

실행을 일시 중지하고 Unity에 제어 권한을 반환한 후, 다음 프레임에서 중단했던 위치에서 계속할 수 있는 메서드이다.
작업을 다수의 프레임에 분산할 수 있다. → 단일 스레드 환경인 유니티에서 비동기 처리가 필요할 때 활용한다.

주의
비동기처럼 동작하지만 비동기 방식은 아니다.
멀티 스레딩 모델의 비동기 방식은 병렬로 처리되기 때문에 함수 A의 완료와 함수 B의 실행 시점이 일치하지 않지만,
코루틴에서는 순차적으로 처리된다. (코루틴에서 작업이 늦을수록 다음 작업도 딜레이되는 현상이 발생하는 이유이기도 하다)

동기식(Synchronous) VS 비동기식(Asynchronous)

  • 동기식 : 먼저 시작된 하나의 작업이 끝날 때까지 다른 작업을 시작하지 않고, 기다렸다가 다 끝난 후 새로운 작업을 시작하는 방식
  • 비동기식 : 먼저 시작된 작업의 완료 여부와 상관없이 새로운 작업을 시작하는 방식

비동기식 VS 멀티스레딩
비동기는 일(task)의 순서에 관한 것이고, 멀티스레드는 작업자(worker)에 관한 것이다.
예를 들어, 할 일이 밥먹기, 청소하기가 있을 경우,
비동기는 “음식을 주문하자마자 청소 시작 후 음식이 도착하면 밥을 먹는다”라면, 멀티스레드는 “할 일을 여러명에서 같이 한다”이다.
멀티스레이면서 동기일 수 있고, 멀티스레드이면서 비동기일 수 있다.
멀티 스레드이면서 동기일 경우, 여러 공간에서 순새도로 작업을 하는 것이고, 멀티스레드 이면서 비동기이면 여러 공간에서 순서를 신경쓰지 않고 작업하는 것이다.

코루틴 구현

IEnumerator를 사용하여 작성되며 yield return으로 멈춘 시점에서 다시 시작한다.

IEnumerator 함수이름()
{
	yield return // + 조건
    // 함수 내용
}

StartCoroutine(함수이름()); //코루틴 시작
StopCoroutine(함수이름); //코루틴 종료
StopAllCoroutines(); //모든 코루틴을 종료
  • 반드시 IEnuemrator을 반환해야한다.
  • yield return을 만나면 코루틴 호출 위치로 돌아가고, yield return 이후에 있는 구문은 조건에 맞게 대기 후 수행한다.
  • yield break를 만나면 코루틴이 종료된다.

[ yield return + 종류(조건) ]

종류(조건)설명
null다음 프레임까지 대기 (Update()가 끝날 때 호출)
new WaitForEndOfFrame()모든 랜더링 작업이 끝날 때까지 대기
(한 프레임워크가 완전히 종료될 때 호출)
new WaitForFixedUpdate()FixedUpdate가 끝날 때 호출
new WaitForSeconds(float)지정한 초(float)만큼 대기 후 호출
new WaitForSecondsRealtime(float)지정한 초(float)만큼 대기 후 호출
(단, Time.timeScale의 영향을 받지 않는 절대적인 시간만큼 대기함)
new startCoroutine(string)다른 코루틴이 끝날 때까지 대기
new WaitWhile(bool)update와 LateUpdate 사이에서 호출되며, 결과값이 만족하면 대기,
만족하지 않으면 yield return 이후 구문이 실행됩니다.
new WaitUntil(bool)update와 LateUpdate 사이에서 호출되며, WaitWhiler과 반대로
결과값이 만족하면 yield return 이후 구문이 실행됩니다.

⇒ yield return을 사용하여 반환 위치를 기억하다가 다음 호출 때 반환 위치 이후부터 실행할 수 있도록 한다.

코루틴 장단점

장점

  • 비동기식 처리가 가능하다
  • 프레임 독립적: 코루틴은 프레임 독립적입니다. 필요한 순간에 언제든지 게임 로직을 시작하고 일시 중지할 수 있다.

단점

  • 메모리 낭비 : 코루틴을 실행할 때마다 IEnumerator 인터페이스에 대한 객체가 생성된다. 코루틴 생성마다 새로운 가비지(IEnumerator)를 만들어내어 과도한 사용은 메모리 부담을 초래할 수 있다.
  • 코드 복잡성 : 코루틴을 오용하면 코드가 복잡해질 수 있습니다. → 지나치게 중첩된 코루틴은 유지 관리와 디버깅을 어렵게 만들 수 있다.

Invoke

원하는 함수를 일정 시간 후에 호출하거나 일정 시간마다 반복해서 호출할 수 있게 해주는 기능으로 Monobehaviour 클래스에서 제공되는 함수이다. (함수 지연 시작 기능)
함수의 이름과 대기할 시간 값을 매개변수로 받는다. (그 외의 매개변수는 전달이 불가능하다)

1
Invoke( "함수명"(string) , 지연시간(float));

Monobehaviour가 비활성인 상태에서도 지연시작이 가능하다.
(Invoke 후 오브젝트나 컴포넌트가 비활성인 상태가 되어도 지연 시작이 가능하다)
하지만, 코루틴은 비활성 상태에서는 작업이 이뤄지지 않는다.

Thread

프로그램 내에서 실행 흐름을 나타내는 가장 작은 단위 일반적으로 하나의 프로세스는 여러 개의 스레드를 포함할 수 있다. 스레드는 프로세스 내의 코드 실행을 담당하며 각 스레드는 독립적으로 실행될 수 있다.
→ 서로 다른 프로세서 코어에서 병렬로 동시 실행이 가능하며 메인 스레드와 독립적인 코드로 실행이 가능하다.
보통 백그라운드 계산이나 Unity 오브젝트와 직접 상호작용할 필요가 없지만 시간이 오래 걸리는 작업을 수행한다.
Unity 메인 스레드 이외의 스레드에서 Unity 오브젝트나 컴포넌트에 직접 액세스 하거나 수정하지 않도록 주의해야 한다.

코루틴은 단일 스레드 환경에서 동작하는 비동기 처리 방법으로 유니티에서 제공하는 기능인 반면
스레드는 코드를 동시에 실행할 수 있는 일반적은 프로그래밍 기능이다.

Job System

스레드를 대신하여 잡을 만들어 유니티에서 안전한 멀티스레딩을 구현하는 시스템이다.
잡 대기열에 잡을 배치하면 워커 스레드가 잡 대기열에서 항목을 가져와 실행한다.
Native Container를 이용해 잡의 수행 결과를 메인 스레드와 공유한다.

잡(job)이란?
특정한 단일 작업을 수행하는 작은 작업 단위이다. 메서드 호출의 동작과 유사한 방식으로 파라마터를 수신하고 데이터 작업을 수행합니다.

워커 스레드
워커 스레드는 추가로 생성되어 별도의 작업을 처리한다. (일반적으로 프로그램은 메인 스레드에서 실행됨)
메인 스레드는 사용자 인터페이스와 같이 반응성이 중요한 부분에 집중하고, 워커 스레드는 시간이 많이 소요되는 작업을 처리한다.

NativeContainer
잡의 결과는 각각의 본사본안에 격리되어 있다. 이를 메인 스레드와 공유하기 위한 공유 메모리 타입을 NativeContainer라고 한다.

[잡 시스템에 대한 자세한 설명]

This post is licensed under CC BY 4.0 by the author.