Deff_Dev

[Unity] 코루틴 본문

면접 질문 정리/Unity

[Unity] 코루틴

Deff_a 2024. 7. 16. 12:22

1. 코루틴의 동작원리에 대해 설명해주세요.

  • Coroutine은 IEnumerator를 이용하여 함수를 작성하고 yield return을 사용하여 특정 조건이 충족될 때까지 실행을 일시 중단하고, 그 후에 실행한다.
  • StartCoroutine을 이용하여 해당 Coroutine을 실행할 수 있고, Unity의 메인 스레드에서 동기적으로 처리된다.
  • YieldInstructions 키워드
더보기

FixedUpdate 이후

  • yield return new WaitForFixedUpdate()
    • 모든 스크립트의 FixedUpdate 함수가 실행이 끝난 후에 yield return new WaitForFixedUpdate() 이후 내용을 실행합니다.

Update 이후

  • yield return null
    • 현재 프레임의 모든 Update 함수가 실행이 끝난 후에 yield return null 이후 내용을 실행합니다.
  • yield return new WaitForEndOfFrame()
    • 모든 Update 함수가 실행이 끝나고 화면 렌더링까지 끝났을 때 yield return new WaitForEndOfFrame() 이후 내용을 실행합니다.

조건이 만족하는 경우

  • yield return new WaitForSeconds(float)
  • yield return new WaitForSecondsRealtime(float)
    • 설정한 시간(초)가 지나고 이후 내용을 실행합니다. (Realtime은 Time.timeScale에 영향을 받지 않음.)
  • yield return new WaitUntil(조건)
    • 설정한 조건의 값이 true일때 yield return new WaitUntil(조건) 이후 내용을 실행합니다.
  • yield return new WaitWhile(조건)
    • 설정한 조건의 값이 false일때 yield return new WaitWhile(조건) 이후 내용을 실행합니다.
  • yield return startCoroutine(IEnumerator)
    • 해당 코루틴이 끝난 후 yield return startCoroutine(string) 이후 내용을 실행합니다.
  • yield return www
    • www 객체로부터 데이터의 다운로드를 기다리고 다운로드가 완료된 후에 이후 내용을 실행합니다.
    • 주로 웹 리소스 다운로드나 HTTP 요청에 사용됩니다.
  • yield return new YieldInstruction()
    • 사용자 정의한 YieldInstruction 타입을 사용하여 특정 조건이나 상황을 기다린 후, 이후 내용을 실행합니다.
  • yield break
    • 현재 실행중인 코루틴을 즉시 종료한다.

2. Invoke와 코루틴의 차이에 대해 설명해주세요.

  • Invoke
    • Invoke는 단순히 일정 시간 뒤에 해당 함수를 실행하는 함수이다.
    • 매개변수 전달은 불가능하다.
    • 오브젝트가 비활성화 되더라도 Invoke는 계속해서 동작하기 때문에 CancelInvoke를 이용하여 Invoke를 중단시키거나, 오브젝트를 삭제하여 Invoke를 종료시켜야한다.
  • Coroutine
    • Coroutine은 프레임 단위로 실행을 일시 중단하고 재개할 수 있으며 시간 초가 아닌 다양한 조건을 설정할 수 있다.
    • 매개변수 전달이 가능하다.
    • Coroutine은 Invoke와 달리 다양하고 복잡한 처리가 가능하기 때문에 활용 범위가 넓다.
    • 오브젝트가 비활성화되면 해당 스크립트의 Coroutine은 종료된다.

3. InvokeRepeating을 통해 반복 실행 중인 메서드는 오브젝트를 비활성화하면 멈출까요?

InvokeRepeating(string methodName, float time, float repeatRate)
  • InvokeRepeating은 MethodName을 가진 함수를 time 초 뒤에 repeatRate 초 마다 반복해주는 함수이다.
  • InvokeRepeating은 오브젝트의 활성화 유무와 상관없이 동작하기 때문에 멈추지 않는다.
  • CancelInvoke를 이용하여 Invoke를 중단시키거나, 오브젝트를 삭제하여 Invoke를 종료시켜야한다.

4. Coroutine을 통해 반복 실행 중인 메서드는 오브젝트를 비활성화하면 멈출까요?

  • CoroutineMonoBehavior 스크립트로 실행되기 때문에 오브젝트가 비활성화된다면 MonoBehavior 스크립트도 비활성화되기 때문에 Coroutine은 멈춘다.
  • 그렇기 때문에 비활성화된 스크립트의 StartCoroutine으로 Coroutine 호출하면 에러가 발생한다.
    • Coroutine couldn't be started because the the game object 'GameObjectName' is inactive!
  • 오브젝트를 비활성화하여 Coroutine을 멈추기 보다는 StopCoroutine을 이용하여 Coroutine을 멈추는 것이 좋다.

5. 다음 Coroutine 코드의 성능 상 문제는 무엇이 있을까요? 

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); 은 0.1초 동안 기다렸다가 아래의 코드가 실행되는 yieldInstruction 키워드 이다.
  • 하지만 위 코드에서는 WaitForSecondsnew로 계속 메모리에 할당해주고 있기 때문에 GC에 부하를 줄 수 있다.
private IEnumerator Fade()
{
  WaitForSeconds wait = new WaitForSeconds(0.1f);
  Color c = renderer.material.color;
 
  for (float alpha = 1f; alpha >= 0; alpha -= 0.1f)
   {
        c.a = alpha;
        renderer.material.color = c;
        yield return wait;
   }
}

 

그렇기 때문에 고정된 시간을 기다려야된다면 미리 WaitForSeconds 객체를 미리 생성하고 재사용하여 new로 계속 메모리에 할당하는 문제를 해결할 수 있다.

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;
    }
}

 

하지만 고정된 시간을 기다리는게 아니라면 타이머를 작성하는 방법으로 구현할 수 있다.


6. Unity의 Coroutine은 비동기 동작일까요? 비동기 동작이라면 하나의 스레드에서 동작하지 않는걸까요?

동기 (좌), 비동기 (우)

동기적 처리

  • 모든 작업이 순차적으로 실행되고, 하나의 작업이 끝나야 다음 작업이 시작됩니다.

비동기적 처리

  • 여러 작업이 동시에 실행되고, 하나의 작업이 진행되는 동안 다른 작업도 병행해서 실행됩니다.

Coroutine은 비동기적 처리가 아닌 동기적 처리이다.

 

Coroutineyield를 통해 실행을 일시 중단하고 특정 조건이 충족될 때까지 대기하는 방식 때문에 비동기적 처리로 보이지만, 메인 스레드에서 순차적으로 실행되는 동기적 처리이다.

  • 처리 속도가 너무 빨라 동시에 실행되는거 처럼 보인다.

7. 코루틴과 멀티쓰레딩은 어떤 차이가 있는지 설명해주세요.

 

프로세스, 스레드 | Notion

프로그램

cuboid-break-657.notion.site

  • 멀티스레딩은 스레드들이 병렬적으로 실행되는 것을 얘기하고 하나의 프로세스가 동시에 여러 작업을 실행하는 것이 목적이다.
  • CoroutineUnity 메인 스레드에서 동기적으로 실행되므로, 멀티 스레딩이 아닌 단일 스레딩이다.

'면접 질문 정리 > Unity' 카테고리의 다른 글

[Unity] 게임 수학  (0) 2024.07.27
[Unity] JSON과 직렬화  (0) 2024.07.22
[Unity] 최적화  (1) 2024.07.17
[Unity] MonoBehavior와 Unity 생명주기  (0) 2024.07.15