[유니티 중급]_7 인보크(Invoke)

0

유니티 엔진

목록 보기
18/21

Invoke란?

이번에는 유니티의 인보크에 대해서 알아보도록 하겠습니다.
우선 인보크란 유니티 엔진에서 모든 유니티 스크립트의 기본 클래스인 MonoBehaviour 클래스에서 제공되는 함수로써 기본적으로 원하는 함수를 일정 시간 후에 호출하거나 일정 시간마다 반복해서 호출할 수 있게 해주는 기능을 제공합니다.

Invoke 사용

public class 인보크 : MonoBehaviour
{
    void Start()
    {
        Invoke(nameof(ConsoleLog), 3);	// 게임 실행후 3초 뒤 로그 출력 
    }

    public void ConsoleLog()
    {
        Debug.Log("인보크 실행");
    }
}

nameof() : 임의의 기호(형식, 멤버, 변수 등)의 이름에 해당하는 문자열을 돌려줍니다.
EX) nameof(ConsoleLog) 와 "ConsoleLog" 는 같은 의미입니다.

  • 문자열을 입력하는것과 달리 오류가 보이기 때문에 함수의 타이핑 오류를 방지할 수 있습니다.
  • 함수의 이름이 변경되어도 적용되기 때문에 문자열 오류를 미연에 방지할 수 있습니다.

Start 함수에서 Invoke 함수를 호출해줍니다.
이 때 Invoke로 호출될 함수의 이름을 문자열로 넣고
얼마나 시간이 흐른 뒤에 호출될 지를 매개변수로 넣어주면 됩니다.
지금은 3초로 설정하겠습니다.

코드를 저장하고 에디터로 돌아가서 빈 게임오브젝트를 하나 생성하고 컴포넌트를 붙여줍니다.
그 다음 게임을 플레이시켜보면 3초 뒤에 로그가 찍히는 것을 볼 수 있습니다.
이것이 가장 기초적인 인보크 사용 방법입니다.

Invoke 반복 사용 (InvokeRepeating)

그 다음 알아볼 것은 반복 호출되는 인보크입니다.

사용 방법은 Invoke 함수와 비슷합니다.
InvokeRepeating 함수를 입력하고 반복 호출할 주기를 매개변수에 입력합니다.

public class 인보크 : MonoBehaviour
{
    void Start()
    {
    	//3초뒤 함수실행, 이후 1초마다 반복 실행
        InvokeRepeating(nameof(ConsoleLog), 3, 1);	
    }

    public void ConsoleLog()
    {
        Debug.Log("인보크 실행");
    }
}

이렇게 하면 InvokeRepeating이 호출되고 3초 후에 CreateCube 함수가 호출되며 그 뒤로 1초마다 계속해서 반복 호출됩니다.
코드를 저장하고 에디터로 돌아가서 게임을 실행해보겠습니다.
그러면 3초가 지난 후에 1초마다 계속 새로운 큐브가 생성되는 모습을 볼 수 있습니다.

Invoke 멈추기 (CancelInvoke)

그 다음에는 동작 중인 인보크를 멈추는 방법을 알아보겠습니다.

인보크를 멈추기 위해서는 CancelInvoke 함수를 사용하면 됩니다.

void Update()
{
    if(Input.GetKeyDown(KeyCode.Space)) 
    {
    	//스페이스바가 눌리면 반복되고 있는 인보크 전체 종료
        CancelInvoke();		
        
    }
}

이 때 매개변수에 아무것도 넣지 않으면
이 게임오브젝트에서 동작하고 있는 모든 인보크들을 멈추게하고

void Update()
{
    if(Input.GetKeyDown(KeyCode.Space)) 
    {
    	//스페이스바가 눌리면 반복되고 있는 특정 인보크 종료
        CancelInvoke(nameof(ConsoleLog));		
    }
}

매개변수에 함수 이름을 넣으면 그 함수 이름으로 실행된 인보크들만 멈추게 할 수 있습니다.

Invoke 동작 확인 (IsInvoking)

이번에는 인보크가 동작 중인지 확인하는 방법을 알아보겠습니다.
인보크가 동작 중인지 확인하기 위해서는 IsInvoking 함수를 사용하면 됩니다.

 void Update()
 {
     if(Input.GetKeyDown(KeyCode.Space)) 
     {
         Debug.Log(IsInvoking(nameof(ConsoleLog)) ? "사용중" : "사용안함");
     }
 }

이 함수 역시 CancelInvoke 함수와 마찬가지로 매개변수로 함수 이름을 넣으면
그 함수에 대한 인보크가 동작 중인지 확인할 수 있고
동작중이면 true, 동작 중이지 않다면 false를 반환합니다.

 void Update()
 {
     if(Input.GetKeyDown(KeyCode.Space)) 
     {
         Debug.Log(IsInvoking() ? "사용중" : "사용안함");
     }
 }

매개변수를 사용하지 않으면 아무 인보크나 동작하고 있는지를 체크할 수 있습니다.

Invoke 주의 사항

추가로 유니티 엔진에서 게임오브젝트의 Update 함수과
코루틴 같은 기능은 게임오브젝트나 컴포넌트가 비활성화되면 동작을 멈추는 것을 알고 있으실 겁니다.
하지만 인보크 기능은 해당 게임오브젝트나 컴포넌트가 비활성화되어도 동작을 멈추지 않습니다.

인보크를 멈추기 위해서는 반드시 CancelInvoke 함수를 호출하거나 게임오브젝트 자체를 파괴해야 합니다.

Invoke와 코루틴

이렇게 인보크를 사용하면 원하는 함수를 일정 시간이 지난 후에 호출하거나
원하는 시간 간격으로 호출할 수 있는데
이 기능은 코루틴을 사용해서도 똑같이 구현할 수 있습니다.

  • Invoke는 호출하는 함수에 직접적으로 매개변수를 전달할 방법이 없지만
    코루틴은 매개변수에 인자를 전달할 수 있습니다.

  • Invoke로 호출된 함수의 반환값은 가져올 수 없습니다.

  • 코루틴은 게임오브젝트나 스크립트가 비활성화 된다면 동작을 멈추지만,
    Invoke는 게임 오브젝트가 파괴되지 않는 이상 멈추지 않습니다.

  • Invoke는 내부적으로 타이머에 의해 해당 시간이 되었는지 체크하여 시간이 되면 호출하는 방식이고
    코루틴은 매 프레임마다 체크하여 돌아갈 지점으로 돌아가는 방식입니다.

그리고 유니티 공식 문서를 보면 성능 향상과 유지보수를 위해서는
코루틴을 사용할 것을 권장
하고 있습니다. 우선 성능적인 측면을 보자면
인보크는 함수를 문자열로 된 이름으로 찾아서 사용하고 있습니다.

이렇게 문자열 함수 이름으로 함수를 찾아서 사용하기 위해서는
C#의 리플렉션이라는 기능을 사용하게 되는데
이렇게 문자열 함수 이름으로 리플렉션을 통해서 함수를 동작시키는 과정은
직접 함수를 호출하는 것에 비해서 수 천 배 정도 느리다고 합니다.

물론 컴퓨터의 사양이 많이 상승한 최근에는 유의미한 성능 저하는 당장 일어나지 않겠지만
인보크를 남용하면서 게임을 만들다보면 게임의 사양이 많이 올라갔을 때
최적화를 위해서 인보크를 사용하는 코드를 대부분 갈아엎어야 할 수도 있습니다.

따라서 아주 간단한 동작을 구현하기 위해서 Invoke를 사용하고,
성능을 위한 동작은 코루틴을 이용하는 것이 좋습니다.

0개의 댓글