코루틴이란?
동작 원리
- 코드 내에서 구문 실행 도중 처리를 대기시키거나, 함수를 병렬로 동시에 처리할 수 있도록 한다.
- yield return을 호출하여 특정 시점까지 대기가 가능하다.
yield return null : 다음 프레임에 실행을 재개한다.
yield return new WaitForSeconds : 지정된 시간 후에 재개한다.
yield return new WaitForSecondsRealtime : Time.timescale 값에 영향을 받지 않고 지정된 시간 후에 재개한다.
yield return new WaitForFixedUpdate : 모든 스크립트에서 모든 FixedUpdate가 호출된 후에 재개한다.
yield return new WaitForEndOfFrame : 모든 카메라와 GUI가 렌더링을 완료하고, 스크린에 프레임을 표시하기 전에 호출된다.
yield return StartCoroutine() : 코루틴을 연결하고 코루틴이 완료된 후에 재개한다.
- StartCoroutine()으로 실행 가능하며, Coroutine이라는 변수를 선언해 실행한 코루틴을 담을 수 있다.
Coroutine coroutine = StartCoroutine("함수 이름"); // 매개변수 하나까지만 전달 가능
Coroutine coroutine = StartCoroutine(함수()); // 성능적 이점 볼 수 있음
- Coroutine은 Game Logic Layer에 위치하며 Update와 함께 yield를 사용하여 루틴을 번갈아가며 실행한다. 이 yield를 반환, 즉 양보하는 시점을 프로그래머가 조율할 수 있기 때문에 원하는 타이밍에 맞추어 코드를 실행하고 종료할 수 있다.
- Ienumerator 관련 공부하기
Unity 코루틴(Coroutine) 이해하기: 동작원리 및 구현
Unity 코루틴이란? 무의식적으로 코루틴은 쓰레드가 생성되는 멀티스레드 방식으로 느껴질 수 있다. 하지만 코루틴은 싱글 스레드로 비동기 방식을 구현한다. 따라서 실제로 병렬 처리가 아니다.
planek.tistory.com
사용 예시
특정 간격으로 반복적으로 작업을 수행할 때,
스킬 쿨타임 돌릴 때 등
Invoke와 코루틴의 차이
코루틴
- 매개변수 전달 O
- GameObject가 비활성화 되면 동작을 멈춘다. 다시 활성화 되더라도 실행되지 않는다
- 프레임 단위로 실행을 일시정지, 시작할 수 있고 시간 초 뿐 아니라 다양한 조건을 넣어 복잡한 처리를 할 수 있다.
Invoke
- 매개변수 전달 X
- GameObject가 비활성화 되더라도 동작한다.
- InvokeRepeating을 통해 반복적으로 함수를 실행시킬 수 있다.
-> CancelInvoke 혹은 오브젝트를 파괴하여 종료해주어야 한다.
- 지연 시간 뒤에 함수를 실행시킬 수 있다. (단순히 일정 시간 뒤에 함수를 실행시킬 뿐이다)
Invoke("함수명", "지연시간");
- Reflection을 통해 값을 가져온다. (코루틴 보다 느리다)
Reflection
프로그램 실행 중 어셈블리의 내용을 확인하거나, 검사하려는 경우 사용되는 기능
코루틴과 멀티쓰레딩의 차이
코루틴
- 코루틴은 동기 동작이다
동기 => 요청을 보낸 뒤 그 요청의 결과값을 얻기까지 작업을 멈추는 것
비동기 => 요청을 보낸 뒤 그 요청의 결과값이 오지 않아도 다른 작업을 수행하는 것
- 단일 스레드에서 실행된다 (유니티는 단일 스레드)
- 코루틴은 yield return를 통해 현재 위치를 기억을 하고 수행 권한을 넘긴다. 이 과정이 마치
여러 개의 쓰레드가 동시에 동작하는 것과 같게 보이는 것.
멀티 쓰레드
- 한 프로세스 내에 실행되는 여러 개의 작업의 단위
- 프로세스는 독립된 힙 메모리 영역을 할당받고, 그 프로세스 내의 쓰레드는 독립된 스택 메모리 영역을 할당받는다.
- 여러 작업을 수행해야할 때 스케쥴링이 이루어진다
(스케쥴링 : 어떤 쓰레드 작업을 먼저 수행할지, 어떤 쓰레드를 더 많이 수행해야 효율적인지)
예시
1. InvokeRepeating을 통해 반복 실행 중인 메서드는 오브젝트를 비활성화하면 멈출까요?
-> 멈추지 않는다.
2. Coroutine을 통해 반복 실행 중인 메서드는 오브젝트를 비활성화하면 멈출까요?
-> 멈춘다. (비활성화 후 다시 오브젝트를 활성화 시키더라도 코루틴은 실행되지 않는다)
3. 다음 Coroutine 코드의 성능 상 문제는 무엇이 있을까요? (Hint : 메모리)
IEnumerator Fade()
{
Color c = renderer.material.color;
for (float alpha = 1f; alpha >= 0; alpha -= 0.1f)
{
c.a = alpha;
renderer.material.color = c;
yield return new WaitForSeconds(.1f);
}
}
yield return new WaitForSeconds(.1f);
- 위의 코드에서 new를 통해 새로운 인스턴스를 생성하고 있다.
이 과정에서 Garbage가 생성된다.
캐싱하여 해당 코드의 성능을 높일 수 있다.
- 고정된 시간이 아닌 경우? -> 따로 타이머를 만들어 타이머 마다 실행되도록 한다
private IEnumerator Fade(flaot delayTime)
{
Color c = renderer.material.color;
float curTime = 0f;
bool isReady = false;
for (float alpha = 1f; alpha >= 0; alpha -= 0.1f)
{
if (!isReady)
{
curTime += Time.deltaTime;
if (curTime >= delayTime)
isReady = true;
}
else
{
c.a = alpha;
renderer.material.color = c;
isReady = false;
curTime = 0f;
}
yield return null;
}
}
4. Unity의 Coroutine은 비동기 동작일까요? 비동기 동작이라면 하나의 스레드에서 동작하지 않는걸까요?
-> 동기 동작이다. 다만 수행 속도가 너무 빨라 비동기 동작 처럼 보이는 것이다.
유니티는 한 번에 한 동작만 수행하는 단일 스레드 방식을 사용한다.
즉 코루틴은 하나의 단일 스레드에서 비동기 처럼 작동하는 동작이다.
'Study > 개념 정리' 카테고리의 다른 글
[Study] Tree (0) | 2024.07.18 |
---|---|
[Study] 최적화 (0) | 2024.07.17 |
[Study] MonoBehaviour와 Unity 생명주기 (0) | 2024.07.15 |
[Study] Queue (0) | 2024.07.12 |
[Study] Stack (0) | 2024.07.11 |