CS/C# & Unity

[Unity]코루틴과 스레드의 차이

혀니리리 2023. 9. 23. 19:37
728x90

1.Unity는 기본적으로 멀티쓰레드를 지원하지 않음

Monobehavior에서 상속받아서 Thread를 사용하려고 하면 경고문 or 에러가 발생함.

메인쓰레드 하나로 생명주기를 돌며 update문을 실행하면서 1/60초에 한 번씩 이 메인쓰레드의 실행이 반복됨

 

 

2.Unity에서 싱글쓰레드를 사용하는 이유

상용 엔진에서는 async/await를 사용해야만 하는 경우가 극히 드뭅니다. 일반적으로 그 외적인 방법으로도 컨트롤 할 수 있는 영역 내에서 스크립팅이 진행되고, Scalable한 비동기 API를 제공한다고 해도 그 효과를 적극적으로 누릴 수 있는 분야는 다소 제한적이기 때문입니다. 렌더링을 비롯한 게임 로직을 비동기로 동시에 사용할 수 있게 제공하더라도 그 효율성보다 그 준비단계에서의 부담이 더 크므로 그 필요성을 느끼지 못하는 것입니다. 
(사용자의 입장에서 async/await를 사용하고 싶을 수도 있지만, 엔진 개발 및 제공자의 입장에서 매력적인 옵션은 아닙니다.)
결과를 두고 봤을 때는 같은 결과를 출력하고 있지만, 코루틴은 하나의 쓰레드에서 스케쥴링으로 관리가 되고 있습니다. 반면 멀티 쓰레드로 구성을 했을 경우, 예외 상황이 많이 생기며 (주로 데드락)
각 프로세스마다 우선권을 주기 위해서 관리되는 기법들도 있습니다. (Join() 호출, 뮤텍스, 셰마포어)

(출처: Unity, 코루틴과 멀티쓰레드의 차이 (tistory.com) Unity: 비동기와 코루틴을 혼동하지 않기 (jeon.sh))

 

 

3.Coroutine이란? (사용이유)

의미: 실행을 중지하여 Unity에 제어권을 돌려주고, 계속할 때는 다음 프레임에서 중지한 곳부터 실행을 계속할 수 있는 기능 (유니티 매뉴얼)

사용 이유: Update문의 실행과 별개로 어떤 동작만을 어떤 시간동안 따로 동작하게 하고 싶을 때

그 동작을 update문에서 초를 받아가며 실행하려고 하면 그때마다 object를 불러와야 하며 부하가 심각해짐.

그래서 잠깐 몇 초동안 따로 이 동작을 실행하게 하는 것이 Coroutine임.

멀티쓰레드같지만 멀티쓰레드가 아니라고 함. 

 

 

4.Coroutine 동작 원리

StartCoroutine으로 코루틴문이 실행되면 

-> Unity에게 제어권을 넘겨줌

-> 유니티 생명주기에서 yield 로 시작하는.. (주로 update문에 많이 포진) 에서 return되어야 할 차례가 되었는지 봄

-> 차례가 되었다면 다음 프레임에서 중지한 곳부터 실행을 계속함

 

 

5.Coroutine을 멀티쓰레드로 혼동하는 이유

public class FadeOut : MonoBehaviour {

	private SpriteRenderer spriteRenderer;

	void Start () {
		spriteRenderer = GetComponent<SpriteRenderer> ();
	}

	void Update () {
		Color color = spriteRenderer.color;
		if (color.a > 0.0f) {
			color.a -= 0.1f;
			spriteRenderer.color = color;
		}
	}
}

위와 같이 fadeOut을 구현하고자 할 때 update내에서 알파값을 줄이면 싱글스레드와 같이 작용하는 것을 볼 수 있음 

하지만 Coroutine을 이용하면

public class FadeOut : MonoBehaviour {

	private SpriteRenderer spriteRenderer;

	void Start () {
		spriteRenderer = GetComponent<SpriteRenderer> ();
		StartCoroutine ("RunFadeOut");
	}

	void Update () {
		
	}

	IEnumerator RunFadeOut() {
		Color color = spriteRenderer.color;
		while (color.a > 0.0f) {
			color.a -= 0.1f;
			spriteRenderer.color = color;
			yield return new WaitForSeconds(0.1f);
		}
	}
}

update문과 별개로 주어진 시간동안 따로 동작하기 때문에 비동기(직렬 처리)로 보일 수 있음

 

 

6.Coruoutine 사용하지 않을 시 부작용 & 사용했을 때의 장점 & 사용 시 단점

사용 안 할 시 부작용: 매 프레임을 그릴때마다 호출되며 60fps의경우라면 초당 60번의 Update() 함수 호출이 발생

=> 안타깝게도 기기의 성능이나 상황에 따라 프레임 드랍(Frame drop)이라는 상황이 발생

(60fps의 게임일지라 하더라도 디바이스의 성능에 따라 그 이하로 떨어질 수 있다는 의미)

 

사용 시 장점: 프레임율에 영향을 받지 않는 시간 기반의 서브루틴을 구동할 수 있게 되었습니다.

(출처: Unity C# – Coroutine 알아보기 | 아이군의 블로그 (theeye.pe.kr))

 

사용 시 단점:

1. 오브젝트가 비활성화 되면 코루틴은 정지한다.

2. Garbage를 많이 생성한다.

(코루틴을 시작하기 위한 StartCoroutine() 메서드는 이 코루틴을 관리하기 위해 인스턴트가 생성된다.

=> 캐싱을 통해 해결 가능)

 

 

7.Thread란?

하나의 프로세스 단위

 

 

8.Thread와 Coroutine의 차이점

가장 큰 차이를 보이는 지점이 여러개의 쓰레드/코루틴을 동시 실행시킬 때일 것이다.

coroutine: 만약 세 코루틴이 동시에 실행이 시작되었을 때 ABCABCABC 이런 식으로 세개의 코루틴을 잘게 쪼개어 비동기처럼 보이지만 실제론 동기로 세 코루틴이 동시에 실행되는 것처럼 보이게 한다.

각각의 코루틴 반환 시기가 다르다면

yield 확인하는 구간에서 반환시기를 계속해서 체크하며 빠른 것부터 반환한다.

 

Thread:

각각 다른 프로세스를 만들어 비동기로 병렬로 처리된다.

먼저 리턴되는 쓰레드가 먼저 끝나는 형태이다.

동시에 여러 코루틴이 수행되는 경우 프레임별로 잘게 쪼개져 번갈아가며 수행되어 비동기처럼 보이는 것임

 

 

(출처: 유니티 코루틴 / Unity Coroutine :: Mist16's Dev Blog (tistory.com)  Unity, 코루틴과 멀티쓰레드의 차이 (tistory.com))

728x90

'CS > C# & Unity' 카테고리의 다른 글

직렬화와 역직렬화  (1) 2023.12.12
스태틱 게임오브젝트와 배칭  (0) 2023.10.01
드로우콜과 배치  (0) 2023.10.01
[C#]박싱 언박싱  (0) 2023.09.27
유니티 생명주기  (0) 2023.08.21