본문 바로가기
개발/Unity 내일배움캠프 TIL

Unity 인보크(Invoke)와 코루틴(Coroutine) 정리

by 석시 2023. 8. 10.



들어가며

이번에 했던 프로젝트를 하고 나서, 가장 많이 느꼈던 점은 Invoke를 너무 남발한 거 같다는 점이다.

해당 함수 때문에 버그가 발생했을 때, 찾기도 버거웠을 뿐더러 (Invoke는 함수를 string으로 받기 때문에 참조 함수 목록에 들어가지 않게 된다.)

시전 타이밍을 스크립트의 코드 순서가 아닌 시간으로 정한다는 것이 게임을 구현하는데 있어 너무 불안요소였다.

따라서 이번에는 아예 Invoke에 대해 정리해보고 어느 때 쓰면 좋을지 알아보는 시간을 가지자.

인보크 기본

인보크는 MonoBehaviour 클래스에서 제공되는 함수이다.

MonoBehaviour가 뭐냐구요?

일단 유니티 엔진에서 모든 유니티 스크립트의 기본 클래스라는 것만 알아둡시다.

스크립트를 생성해보면 기본적으로 MonoBehaviour를 상속받도록 되어 있다.

기본적인 기능은 원하는 함수를 일정 시간 후에 호출하도록 하는 기능이다.

인보크 사용방법

InvokeRepeating

한 번만 호출하려면 Invoke, 일정 시간마다 반복적으로 호출하려면 InvokeRepeating을 사용하면 된다.

Invoke("pauseGame", 0.5f);
InvokeRepeating("blink", 1.0f);

골때리는 건, 함수 인자를 string으로 받는다는 점이다.

함수 트래킹이 매우 힘들다.

CancelInvoke

InvokeRepeating을 멈추기 위해선 CancelInvoke를 사용하면 된다.

CancelInvoke();
CancelInvoke("blink");

이 때 인자로 아무것도 넣지 않으면 모든 인보크를 멈추게 하고, 함수 이름을 넣게 되면 해당 인보크만 멈추게 된다.

IsInvoking

인보크가 동작 중인지 확인하려면 IsInvoking을 사용하자.

IsInvoking();
IsInvoking("blink");

사용방법은 CancelInvoke와 똑같다.

인자로 아무것도 넣지 않으면 인보크가 하나라도 있으면 true, 아니면 false이다.

인자로 넣으면 해당 함수가 Invoke 중인지 알 수 있다.

인보크 주의점

유니티 엔진에서 오브젝트의 스크립트에 작성된 Update() 함수 같은 경우 해당 오브젝트나 스크립트가 비활성화 되면 작동을 멈춘다.

하지만 인보크의 경우는 다르다.

오브젝트가 비활성화된다 하더라도 인보크는 멈추지 않는다.

인보크를 멈추기 위해선

  • CancelInvoke() 사용
  • 오브젝트 파괴 (Destroy)

반드시 둘 중에 한 방법을 사용해야 한다.

코루틴

비슷한 것중에 Coroutine이라는 것이 있다.

사실 기능은 아예 똑같다.

형태는 다음과 같다.

IEnumerator FunctionName()
{
	yield return; // + 조건
    // 함수 내용
}

해당 함수를 호출함으로써 함수 안의 내용을 예약할 수 있는 것이다.

인보크와 코루틴의 대표적인 차이는 두 개가 있다.

  • 인자로 string을 받지 않는다. (즉 훨씬 빠르다)
  • 오브젝트나 스크립트를 비활성화하면 내부의 코루틴은 멈춘다.

Invoke는 string을 인자로 받기 때문에 함수를 따로 찾는 과정이 필요하다.

때문에 작동에 추가적인 시간이 발생한다.

따라서 어지간하면 코루틴을 사용하도록 하자.

코루틴 사용 방법

yield return 뒤에 여러 가지를 붙여 사용할 수 있다.

float seconds = 1.0f;

yield return null; // 다음 프레임에 실행
yield return new WaitForSeconds(seconds); // 게임 시간으로 1초만큼 기다렸다가 실행
yield return new WaitForSecondsRealtime(seconds); // 현실 시간으로 1초만큼 기다렸다가 실행
yield return break; // 해당 시점에서 코루틴 함수 종료

참고할 건, return처럼 함수가 아예 끝나는 것이 아니라 yield break;를 제외하고는 뒤의 코드들도 실행이 된다!

IEnumerator CoroutineFunction(int count)
{
    int i = 0;
    while(i < count)
    {
        yield return null;
        Debug.Log("Coroutine " + i);
        i++;
    }
}

IEnumerator TestCoroutine(int count, float time)
{
    yield return new WaitForSeconds(time);

    int i = 0;
    while(i < count)
    {
        yield return null;
        Debug.Log("Coroutine " + i);
        i++;
    }
}

코루틴 함수 호출과 관련된 기능들은 다음처럼 사용할 수 있다.

StartCoroutine

StartCoroutine(CoroutineFunction(10)); // 해당 코루틴 시작 및 매개변수 전달
StartCoroutine("CoroutineFunction", 10); // 해당 코루틴 시작 및 매개변수 전달

StartCoroutine(CoroutineFunction(10, 10f)); // 매개변수 두개 전달

참고로 string을 인자로 쓸 경우 매개변수를 한 개밖에 전달하지 못한다.

StopCoroutine

IEnumerator funcCode = StartCoroutine(CoroutineFunction(10, 10f));

StopCoroutine(funcCode);

리턴값으로 IEnumerator를 받는 이유가 해당 코루틴의 코드를 받기 위해서이다.

StopCoroutine("CoroutineFunction");
StopAllCoroutines();

인자로 string을 넣어줄 수도 있고,

StopAllCoroutines();로 모든 코루틴을 중단시킬 수 있다.


Uploaded by N2T