Unity - Coroutine

2024. 4. 19. 21:05Unity/Unity 학습정리

게임을 만들다보면 원하는 동작을 시간 간격을 두고 반복 실행을 시키고 싶을 때가 있다. 물론 Update() 함수가 프레임마다 상태를 업데이트해주는 기능을 제공해주지만, 어느 순간에는 반복을 멈추고 싶을때가 있고 다수의 프레임에 분배를 못한다. 예를들어 몇초간격으로 생성되게 하는 오브젝트 혹은 몇초간격으로 데미지를 입는 흔히 도트데미지라고 부르는 동작 등 Update()함수에 작성을 하게 되면 프레임단위로 동작하기 때문에 구현하기 쉽지않다. 그래서 동작을 프레임에 분산시켜 내가 원하는 시간에 해당 함수를 동작시킬수있고 멈출 수도 있게 도움을 주는 것이 Coroutine이다.

목차

  1. Coroutine을 사용하는법과 특징
  2. yield return
  3. 마무리

    Unity Documents - Coroutine 

    유니티 공식문서에서 Coroutine을 다음과 같이 설명하고 있습니다.

     

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

    대부분의 경우 메서드를 호출하면 실행을 완료한 뒤 호출한 메서드에 제어와 선택적 반환 값을 반환합니다. 즉 메서드 내에서 발생한 모든 행동은 단일 프레임 업데이트 내에서 발생해야 합니다.

    시간의 흐름에 따른 이벤트의 시퀀스나 절차상의 애니메이션을 포함하기 위해 메서드 콜을 사용하고자 하는 상황에서 코루틴을 사용할 수 있습니다.

    하지만 코루틴은 스레드가 아니라는 점을 명심해야 합니다. 코루틴의 동기 작업은 여전히 메인 스레드에서 실행됩니다. 메인 스레드에 소요되는 CPU 시간을 줄이려면 다른 스크립트 코드에서와 마찬가지로 코루틴의 작업 차단을 방지하는 것이 중요합니다. Unity 내에서 다중 스레드 코드를 사용하려면 C# 잡 시스템을 고려하십시오.

    코루틴은 HTTP 전송, 에셋 로드, 파일 I/O 완료 등을 기다리는 것과 같이 긴 비동기 작업을 처리해야 하는 경우 코루틴을 사용하는 것이 가장 좋습니다."


    Coroutine을 사용하는법과 특징

    IEnumerator FunctionName()
    {
    	...
    	yield return ~;
       	...
    }

    코루틴 작성의 기본은 위와 같다. IEnumerator를 반환형을 가지며 yield return 구문을 사용해야한다.

    여기서 IEnumerator랑 yield return도 처음 접해서 찾아봤더니 C#에 있는 system.Collection 라이브러리에있는 인터페이스였다. 해당 부분은 다음 포스팅에서 공부해서 다루기로하고 이번 포스팅에서는 Unity Coroutine에 대해서 공부하고 다뤘다.

    • StartCoroutine
      • 코루틴을 실행해주는 메서드이고 해당 메서드는 Unity Monobehaviour에서 지원한다.
      • 해당 코루틴을 실행한 객체(Object)가 소유권을 가진다.
    public Coroutine StartCoroutine(IEnumerator routine)
    public Coroutine StartCoroutine(string methodName, object value = null)
    
    StartCoroutine(FunctionName());
    StartCoroutine("FunctionName",10);

    함수를 넣어서 사용하는 기법이 주로 사용되고 특별한 경우아니면 함수이름을 써서 Coroutine을 사용하는 것은 지양된다고한다. 후자의 경우에는 매개변수를 한 개 밖에 전달이 못한다는 단점이 있다.

    • StopCoroutine
      • 실행중인 코루틴을 중지시킨다.
      • 소유권을 가진 코루틴 중 일치하는 코루틴을 종료한다.
    public void StopCoroutine(string methodName)
    public void StopCoroutine(IEnumerator routine)

    위 두 개의 형태는 만약 한가지 Coroutine이 여러개 실행중일때 원하는 Coroutine을 골라서 정지시키기 어렵다. 따라서 아래 메소드를 사용하는것이 좋다.

    public void StopCoroutine(Coroutine routine)
    • StopAllCoroutines
      • 현재 소유권을 가진 모든 코루틴을 중지시킨다.
    public void StopAllCoroutines()

     

    yield return

    유니티에는 yieldInstruction 클래스가 존재한다. 해당 클래스를 상속받아 코루틴을 원하는 대로 다룰 수 있다. 

    //다음 업데이트 호출까지 대기
    yield return null;
    //다음 fixedUpdate 호출까지 대기
    yield return WaitForFixedUpdate();
    //time 시간이 지난후 첫프레임까지 대기
    yield return new WaitForSeconds(float time);
    //time 시간이 지난후 첫프레임까지 대기(timeScale의 영향을 받지 않음)
    yield return new WaitForSecondsRealtime(float time);
    //현재 프레임의 렌더링이 완료될 때까지 일시 중단되도록 만든다. (모든 요소들이 랜더링되고 사용할 수 있을거같다)
    yield return new WaitForEndOfFrame();

     

     


     

    마무리

     코루틴을 공부하면서 내가 몰랐던 부분을 많이 알게되었다. 코루틴의 특징이나 IEmurator, yield return 그리고 코루틴의 원리 등 내용을 파다보니 한 파트에도 공부할게 엄청 많았다. 특히 코루틴의 특징이나 원리가 매우 중요하게 다가왔으며 해당 내용들을 더 자세히 정리하기 위해 공부를 더 하고 다음 포스팅에 올리기로 마음먹었다.

    개인프로젝트에서도 실제로 코루틴을 사용한 내용이 있는데 막상 원리는 잘 모르고 "그냥 함수를 써보니 이렇게 동작하더라ㅅ"만 알았다. 물론 그정도만 알아도 가벼운 프로젝트를 하는데에는 문제가 없겠지만 정확히 원리를 알고 최적화를 시도할때에도 분명히 적용될거라고 믿고 이론공부도 소홀히 하지 않겠다고 생각했다.

     

     

     

     

     


     

     

     

    'Unity > Unity 학습정리' 카테고리의 다른 글

    Unity - 각도 구하기  (0) 2024.05.16
    Unity - LayerMask  (0) 2024.05.09
    Unity - Coroutine2  (0) 2024.04.22
    Unity Animation  (1) 2024.04.18
    #1 중복 없이 숫자를 뽑아 배열에 저장  (0) 2024.04.15