Unity 개발일지

[Unity] Coroutine(코루틴)에대해 알아보자 본문

Unity 개발

[Unity] Coroutine(코루틴)에대해 알아보자

아머르 2024. 5. 22. 21:49

[코루틴이란?]

코루틴을 사용하면 작업을 다수의 프레임에 분산할 수 있습니다. Unity에서 코루틴은 실행을 일시 정지하고 제어를 Unity에 반환하지만 중단한 부분에서 다음 프레임을 계속할 수 있는 메서드입니다. 대부분의 경우 메서드를 호출하면 실행을 완료한 뒤 호출한 메서드에 제어와 선택적 반환 값을 반환합니다. 즉, 메서드 내에서 발생한 모든 행동은 단일 프레임 업데이트 내에서 발생해야 합니다.

코루틴은 스레드가 아니라는 점을 명심해야합니다. 코루틴의 동기 작업은 여전히 메인 스레드에서 실행됩니다.

(유니티는 단일스레드이다.)

 

 

 

[그래서 코루틴을 사용하면?]

코드 내에서 구문 실행 도중에 처리를 대기시키거나, 순차처리에 함수를 병렬로 동시에 처리하도록 구현할 수 있다.

예를 들면 캐릭터가 중독되어 체력이 감소하는 경우, http 또는 I/O처리와 같이 대기시간이 긴 비동기 작업을 처리하는 데 사용되며(코루틴이 비동기라는 뜻은 아님!) 프레임당 실행되는 Update문으로 처리하기보다는 코루틴을 사용하여 지정한 시간 간격으로 처리하여 성능상 이점을 획득할 수 있다.

 

유니티에서 코루틴은 비동기 작업을 처리하면서도 게임 루프의 제어를 유지할 수 있기 때문에 사용되며

코루틴은 일시 중지, 재개, 일시 중지된 시점부터 실행하는 기능을 가지고 있어서, 일정한 시간 동안 대기하거나 다른 처리를 하고 다시 원래 작업으로 돌아오는 등의 작업을 수행할 수 있다.

 

 

 

[비동기가 뭔데?]

유니티에서는 Awake - Start - Update(반복)의 순으로 도는데 비동기는 간단하게 이 주기에서 벗어나서 따로 실행이 된다. 코루틴은 Update 내에서 엮여서 같이 순환을 하는 점에서 비동기가 아니라 것이다.

 

 

[코루틴의 구성 요소]

코루틴은 단일 스레드에서 동작하며, 하나의 스레드 자원을 나누어 사용한다.

코루틴은 단일 스레드에서 실행되지만, 실행 중인 코드에서 yield 반환문을 만나면 실행을 일시 중지하고,

제어권을 유니티에게 넘긴다. 다시 재개할 때 yield 반환문 이후의 코드부터 실행한다. 이 때 코루틴이 사용하는 스택, 프로세스의 값 등은 메모리에 저장되어있어, 재개되는 시점에서 저장된 상태를 불러온다. 이를 통해 하나의 스레드에서 코루틴과 동기적 코드를 번갈아가며 실행할 수 있다.

코루틴을 구현할 때는 보통 IEnumerator 또는 IEnumerable 인터페이스를 구현하는 방식을 사용하며

yield return 키워드는 반드시 인터페이스를 구현한 메소드 내에서 사용되어야한다.

 

 

<다양한 yield 사용법>

 

 

 

[코루틴의 장점]

1. 처리와 처리 사이에 대기 시간을 넣을 수 있다.

 

2. 여러 작업을 동시에 병렬처럼 보이도록 처리해준다.

 

3. 실제로 병렬처리가 이루어지는 것이 아닌 처리가 빠르게 이루어져 병렬처럼 보여진다.

 

 

 

[코루틴의 단점]

1. 코루틴은 일반적으로 스레드보다 느리다.

 이는 코루틴이 단일 스레드에서 실행되는 반면, 스레드는 여러 개의 코어를 사용하여 병렬로 실행될 수 있기 때문

 

2. 코루틴은 동시에 실행되는 코드 블록의 수를 제한한다.

 

 

 

 

[일반 함수와는 무슨 차이가 있을까?]

반복문을 사용하는 Func1 이라는 함수를 만들었고 Func2와 Func3도 동일 내용만 바꿔서 만들어주었다.

 

Start에서 실행해본다.

 

Func1 - Func2 - Func3 의 순서로 각 함수의 실행이 종료되는 순차적 실행을 한다.

 

 

 

[코루틴을 실행시키는 법]

기본적으로 StartCoroutine(코루틴함수); 로 실행. yield return으로 반환

 

1. 코루틴 함수 자체를 넣기

 

2. 코루틴 함수의 이름을 string으로 넣기

 

3. 코루틴 함수를 Ienumerator, Coroutine 변수에 할당하여 넣기

 

 

 

[코루틴을 써보자]

코루틴은 인터페이스를 상속하므로 반환형을 꼭 구현해주어야 한다.

 

반환형(yield return)이 없으면 Error가 발생한다.

 

아까와 똑같이 코루틴에 for문을 작성해주고 Cor3까지 만들어준 후 실행해보자.

 

코루틴은 StartCoroutine()으로 실행할 수 있다.

 

이번에도 Cor1 - Cor2 - Cor3 의 순차적으로 실행이 된다.

이것으로 코루틴도 일반 메서드(함수)와 같이 실행되는 것을 알 수 있다.

 

 

 

[코루틴을 써보자2]

이번에는 각 코루틴의 for문 안에 yield return을 넣어주어 for문 한바퀴를 돌 때 마다 yield return null을 하게 해주었다.

놀랍게도 for문을 한번 실행한 후 제어권을 Unity에 넘겨서 다음 코루틴이 실행되는 것을 볼 수 있다.

 

 

 

[코루틴을 중지시키는 법]

기본적으로 StopCoroutine(코루틴함수);

 

1. String 형식이나 함수() 형식을 파라미터로 넘긴 코루틴은 정지 X

 

2. Coroutine이나 Ienumerator에 할당한 코루틴만 정지 가능

 

다시말하면 변덕스러운 유니티는 코루틴 실행법 3가지 중 1, 2번은 정지시키지 않고 3번만 정지를 시킨다.

유니티 버전이나 코드에 따라서 1, 2번도 정지가 되긴 하지만 (원래는 정지가 되는게 맞다)

그래서 중간에 코루틴의 제어가 필요한 경우에는 꼭 변수선언을 해서 코루틴을 사용하자!

변수를 할당한 방법으로 화면을 클릭하면 중지하는 코루틴을 작성하고 실행해주었다.

코루틴이 끝나면 "코루틴 끝" 이라는 로그가 출력이 되어야하는데 마우스 클릭을 하니 코루틴이 멈추었다.

 

 

 

[코루틴을 실행시키는 주체는?]

코루틴을 while문으로 바꿔주었다.

while문 아래가 흐릿하게 보인다면 매의 눈을 가진 것이다.

while문이 실행되면 밑의 코드가 실행되지 않는다는 뜻으로 Visual Studio에서 흐릿하게 표시해준 것이다.

실행시키면 코루틴은 계속 돌 것이고, Coroutine 스크립트를 꺼도 코루틴은 돌아간다.

하지만 TestCoroutine 오브젝트를 끄면 코루틴은 중지되고, 꺼진 오브젝트를 다시 켜도 코루틴은 다시 실행되지 않는다.

 

이것으로 보아 코루틴을 실행시키는 주체는 오브젝트라는 것을 알 수 있고,

오브젝트가 SetActive(false) 또는 Destroy가 되었을 경우에 코루틴은 멈춘다.

 

예를 들면 코루틴을 이용하여 버프아이템을 만들었는데 SetActive(true)로 짠 하고 띄웠다가 SetActive(false)를 해버리면

코루틴이 멈춰 버프효과도 멈추게 되는 것이다.

 

코루틴이 병렬이 아니라는 증거인셈!

(병렬이라면 오브젝트가 켜지던지 꺼지던지 스레드가 멈춘 것이 아니기 때문에 실행이 되어야한다.)

 

코루틴은 유니티 생명주기에 붙어있는 함수이기 때문에 오브젝트가 꺼지면 멈춘다!

 

 

 

[Yield를 사용해보자!]

Yield를 사용해보기위해 마우스를 클릭하면 isCheck가 true로 바뀌고 for문을 재개하는 기능을 만들어보았다.

람다식을 활용해서 isCheck를 가져왔다.

마우스 클릭을 하면 bool값이 true가 되어 Coroutine이 재개되는 모습을 볼 수 있다.

 

 

코루틴 내부에서 코루틴도 불러올 수 있다는 사실!

 

 

 

[정리]

1. 같은 코루틴 함수를 여러 번 호출할 수 있다.

 

2. 코루틴 내부에서 코루틴을 호출할 수 있다.

 

3. 특정 코루틴을 멈추려면(StopCoroutine) Inumerator에 할당한 코루틴만 정지가 가능

 

4. StartCoroutine("코루틴 이름")을 사용하여 코르틴을 실행할 경우 오탈자에 주의!

 

5. 코루틴을 사용하는 주체는 해당 스크립트!

 

6. 코루틴 != 비동기

 

 

 

[참고]

 

코루틴 - Unity 매뉴얼

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

docs.unity3d.com

 

 

[Unity] 유니티 코루틴 사용법 - Coroutine 사용 이유

코루틴이란 유니티에서 제공하는 기능으로 코드 내에서 구문 실행 도중에 처리를 대기시키거나 순차처리에 함수를 병렬로 동시에 처리하도록 구현할 수 있습니다. 유니티 api에서는 Coroutine이

codeposting.tistory.com

 

 

싱글스레드(Single thread) vs 멀티스레드 (Multi thread)

오늘은 싱글 스레드와 멀티 스레드가 무엇인가와 이 둘의 장단점에 대해서 알아보자!!일단, 시작에 앞서 이해를 돕기 위해 이 그림을 봐주길 바란다.=> 싱글 스레드와 멀티 스레드의 차이는 이

velog.io

 

반응형