📒 갈무리 - 코루틴(Coroutine)
📌 코루틴이란?(Unity)
- 필요에 따라 일시 정지할 수 있는 함수
- 실행을 일시 중지하고 Unity에 제어 권한을 반환한 후, 다음 프레임에서 중단했던 위치에서 계속 진행할 수 있는 함수
- Unity는 진행 루틴을 가지고 있는데, 이 진행 루틴대로 코드를 실행하다가 StartCoroutine을 만나면 코루틴을 실행하여 진행 루틴에서 빠져나와 코루틴이라는 새로운 루틴을 진행한다. 이때 제어권을 코루틴에게 준다고 표현한다.
- yield를 통해서 Unity의 진행 루틴으로 돌아가면 제어권을 Unity의 진행 루틴으로 넘기는 것이다.
- 여러 처리를 동시에 병렬로 할 수 있도록 해준다. (실제로 병렬 처리가 이루어지는 것은 아니고, 빠르게 왔다 갔다 하면서 실행되기 때문에 병렬 처리 되는 것처럼 보여지는 것)
- 보통 코드를 짜면 스크립트의 절차대로 진행되지만, 코루틴은 매인 동작과 상관없이 병렬처럼 진행될 수 있도록 한다.
📌 코루틴 사용 조건
1. 반환형은 IEnumerator 이어야 한다.
2. yield return이 반드시 존재해야 한다.
📌 yield
yield return null : Update()가 끝나면 실행 (한 프레임 대기)
yield return new WaitForSeconds(float) : 매개변수의 숫자에 해당하는 초만큼 만큼 대기하고 실행
yield return new WailtforSecondsRealtime(float) : 매개변수의 숫자에 해당하는 초만큼 대기하고 실행 (Time.timeScale의 영향을 받지 않는 절대적인 시간을 의미)
yield return new WaitForFixedUpdate() : FixedUpdate()가 끝나고 실행
yield return WaitForEndOfFrame() : 모든 Update()가 끝나고 화면 렌더링까지 끝났을 때 실행
yield return new WaitUntil() : 매개변수의 조건이 true일 때 실행 (실행 위치는 Update()와 LateUpdate() 이벤트 사이)
yield return new WaitWhile() : 매개변수의 조건이 false일 때 실행 (실행 위치는 Update()와 LateUpdate() 이벤트 사이)
yield return StartCoroutine(string) : 매개변수의 이름을 가진 코루틴이 끝날 때까지 대기하고 실행
yield return new www(string) : 매개변수의 이름을 가진 웹의 통신 작업이 끝날 때가지 대기
yield return new Asyncloeration : 비동기 작업이 끝날 때까지 대기(씬 로딩)
📌 코루틴 사용 예제
void Start()
{
StartCoroutine(CoroutineTest());
}
private IEnumerator CoroutineTest()
{
Debug.Log($"1 : {Time.realtimeSinceStartup}");
yield return null;
Debug.Log($"2 : {Time.realtimeSinceStartup}");
yield return new WaitForSeconds(1f);
Debug.Log($"3 : {Time.realtimeSinceStartup}");
}
Output:
1 : 3.019858
2 : 3.032970
3 : 5.057276
다중 코루틴
void Start()
{
StartCoroutine(CoroutineTest());
StartCoroutine("CoroutineTest");
}
private IEnumerator CoroutineTest()
{
Debug.Log($"1 : {Time.realtimeSinceStartup}");
yield return null;
Debug.Log($"2 : {Time.realtimeSinceStartup}");
yield return new WaitForSeconds(1f);
Debug.Log($"3 : {Time.realtimeSinceStartup}");
}
Output:
1 : 3.004708
1 : 3.009927
2 : 3.019537
2 : 3.019891
3 : 4.102481
3 : 4.102903
코루틴과 코루틴 사이에서의 코루틴 정지
void Start()
{
Coroutine coroutine = StartCoroutine(CoroutineTest());
StartCoroutine("CoroutineTest");
StopCoroutine(coroutine);
}
private IEnumerator CoroutineTest()
{
Debug.Log($"1 : {Time.realtimeSinceStartup}");
yield return null;
Debug.Log($"2 : {Time.realtimeSinceStartup}");
yield return new WaitForSeconds(1f);
Debug.Log($"3 : {Time.realtimeSinceStartup}");
}
Output:
1 : 3.023257
1 : 3.028298
2 : 3.037791
3 : 5.273876
코루틴과 코루틴 사이에서의 인터벌
void Start()
{
StartCoroutine(CoroutineTest());
}
private IEnumerator CoroutineTest()
{
Debug.Log($"1 : {Time.realtimeSinceStartup}");
yield return StartCoroutine(CoroutineTest2());
Debug.Log($"2 : {Time.realtimeSinceStartup}");
yield return new WaitForSeconds(1f);
Debug.Log($"3 : {Time.realtimeSinceStartup}");
}
private IEnumerator CoroutineTest2()
{
Debug.Log($"4 : {Time.realtimeSinceStartup}");
yield return null;
Debug.Log($"5 : {Time.realtimeSinceStartup}");
yield return new WaitForSeconds(1f);
Debug.Log($"6 : {Time.realtimeSinceStartup}");
}
Output:
1 : 3.063264
4 : 3.068327
5 : 3.078072
6 : 5.415286
2 : 5.415732
3 : 6.419126
📌 코루틴 사용 주의점
- 코루틴이 종료되는 시점에 특정 시작되는 동작이나 함수가 호출된다면 그 동작에 대해 주석을 남겨 협업하는 개발자에게 알리는 것이 좋다.
- 코루틴이 종료되는 시점에 시작되는 동작이나 호출되는 함수는 코루틴에서 호출되기 때문에 어느 시점에 호출되는지 코드로 파악하기 어려울 수 있기 때문이다.