Unity

유니티 #8 - delay (코루틴, invoke)

kakaroo 2022. 6. 6. 16:40
반응형

씬 전환시 버튼음이 플레이 되자마자 완료되지 않은 상태로 씬 전환이 되어 어색할 때가 있다.
이 때 버튼음의 시간동안 딜레이를 준 다음에 다음 씬으로 넘어가게 한다.

유니티에서 딜레이를 줄 수 있는 방법은 코루틴과 invoke 가 있다.

 

 

코루틴

 

유니티에서 특정 코드가 반복적으로 실행되기 위해서는 Update문에 코드를 작성하면 되는데,

간혹 Update가 아닌 곳에서도 반복적으로 코드가 실행되어야할 필요가 있을 때가 있다.

이럴 때 코루틴을 사용하는 것이 매우 효과적이다.

또한, 업데이트문을 사용하면 원하든 원하지 않든 업데이트문이 매 프레임마다 계속 반복적으로 실행되지만,

코루틴을 사용한다면 자신이 필요한 순간에만 반복하고 필요하지 않을 때에는 전혀 사용하지 않음으로써 자원관리를 매우 효과적으로 할 수 있다.

 

그 밖에도 당장 실행되는게 아니라 일정 시간동안 멈춰있다가 그 뒤에 동작하게 하거나 특정 조건을 부여해서 코드가 실행되도록 할 수도 있다. 사용법도 간단하면서 다양하게 활용이 가능하기 때문에, 코루틴은 실무에서 굉장히 빈번하게 사용되므로 꼭 자세히 알아둘 필요가 있다.

 

크게 2가지의 필수조건이 있다.

1. 코루틴은 IEnumerator라는 반환형으로 시작해야한다.

2. yield retrun이 반드시 함수 내부에 존재해야한다.

결과적으로 코루틴은 이런 모양이 된다.

IEnumerator 함수이름()
{
    yield return // + 조건
    // 함수 내용
}

주석을 확인해보면, yield return 뒤에 +조건이라고 쓰여있는데, 해당 조건 입력되는 코드에 따라서 코루틴의 동작을 다양하게 컨트롤 할 수 있다. (아래 설명)

 

  1. yield return null;  //다음 프레임에 실행 됨
  2. yield return new WaitForSeconds( float );  //매개변수로 입력한 숫자에 해당하는 초만 큼 기다렸다가 실행됨
  3. yield return new WaitForSecondsRealtime( flaot );  //매개변수로 입력한 숫자에 해당하는 초만큼 기다렸다가 실행됨
  4. 그외 : yield return + new WaitForFixedUpdate / WaitForEndOfFrame 등...
  5. yield break;  //코루틴 끝내기

 

2번과 3번의 차이는?

2번은 유니티상에서의 시간을 기준으로 체크하는 것이고, 3번은 현실의 시간을 기준으로 체크하는 것이다.

유니티에서 시간은 TimeScale을 사용해서 느리게하거나 빠르게 조절할 수 있는데, 이 값의 변화에 영향을 받는 것이 2번이고 무관한 것이 3번이다.

 

사용방법은 StartCoroutine 메소드에 실행할 함수를 매개변수로 호출하면 된다.

StartCoroutine(loadScene());	//매개변수로 함수 호출
StartCoroutine("loadScene");	//함수 이름을 큰 따옴표로 감싸기

이렇게 2가지 방법으로 사용할 수 있다.

 

코루틴에서는 실행할 함수의 매개변수를 지정할 수 있다. 매개변수가 있을 경우 사용 방법은 다음과 같다.

StartCoroutine( 메소드이름( 매개변수1, 매개변수2 ) );
StartCoroutine( "메소드이름", 매개변수 );

문자열로 메소드 이름을 적어서 코루틴을 동작시킬 경우 ,를 찍어서 매개변수를 전달할 수 있다.

다만 이 경우에는 매개변수가 1개까지만 전달할 수 있다.

반면, 일반적인 메소드를 호출하는 것처럼 적어준다면 여러개의 매개변수를 전달 할 수 있다.

 

 

코드 적용 예)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;  //LoadScene 을 사용하는 데 필요

public class Replay : MonoBehaviour
{
    public void onClickReplayButton() {
        //SceneManager.LoadScene("GameScene");        
        StartCoroutine(loadScene());
    }

    IEnumerator loadScene() {
        yield return new WaitForSeconds(1.0f);
        SceneManager.LoadScene("GameScene");
    }
}

 


Invoke

Invoke(string methodName, float time);

Invoke를 적은 뒤에 실행할 함수의 이름을 적고 바로 뒤에는 몇 초 뒤에 실행할 것인지를 적어준다.

실행할 함수의 이름을 string으로 입력해야하기 때문에 " " 안에 이름을 입력해야한다.

 

주의!!

보통 게임 오브젝트가 비활성화될 경우 오브젝트가 가지고 있는 스크립트의 Update 함수가 동작을 멈춘다.

그런데, invoke를 사용한 경우 해당 게임오브젝트가 비활성화되더라도 invoke는 계속해서 동작한다.

게임 오브젝트가 비활성화되었음에도 invoke가 존재한다면 컴퓨터 사양을 좀먹게 되는 것이다.

따라서 invoke를 멈추기 위해서는 반드시 비활성화가 아니라 게임오브젝트 자체를 파괴해서 없애거나

invoke를 멈추는 CancelInvoke 함수를 사용해서 인보크를 멈춰주어야한다.

 

 

InvokeRepeating

InvokeRepeating(string methodName, float time, float repeatRate);

해당 메소드는 invoke와 동일하게 지연된 시간 후에 함수를 호출하는데 이것을 반복적으로 수행하게 해준다.

기존의 invoke와 동일하게 매개변수들을 입력한 후에 반복될 시간을 추가로 입력해주면 된다.

ex) InvokeRepeating("1번함수", 2f, 5f)

라고 입력을 한다면 1번 함수를 2초후에 실행한 다음에 5초마다 다시 반복적으로 실행시켜준다.

주의할 점은 3번째 매개변수에 0을 입력할 경우, 아예 InvokeRepeating이 동작하지 않는다.

 

 

 

CancelInvoke

CancelInvoke();

해당 메소드를 매개변수 없이 입력하면 현재 존재하는 모든 invoke를 멈추게 만든다.

만약 매개변수에 함수 이름을 적으면, 해당 invoke만 멈추게 할 수도 있다.

InvokeRepeating() 을 사용했다면, 일정 조건 후에 CancelInvoke() 를 써서 멈추게 만드는 것이 좋다.

 

 

 

IsInvoking()

IsInvoking(string methodName);

invoke가 동작하고 있는지를 bool 값으로 알려준다.

매개변수 값을 넣으면 해당 메소드가 동작 중인지를 알 수 있고, 매개변수를 입력하지 않으면 현재 동작 중인 invoke가 있는지 알 수 있다.

bool 값으로 결과를 리턴하기 때문에 조건문에 작성해서 invoke가 동작 중일때 혹은 동작중이 아닐때에만 무엇을 해라 라는 식의 소스코드 작성이 가능하다.

 


유니티 공식문서에서 invoke보다는 코루틴의 사용을 권장하는 이유는 성능 때문이다.

invoke는 문자열로 함수명을 입력하고 이 문자열을 통해서 함수를 실행하는데, 이 과정에서 C#의 리플렉션 기능이 사용된다. 이렇게 문자열로 리플렉션을 하는 속도가 직접 함수를 호출하는 것보다 훨씬 더 매우 느리다.

PC의 경우 컴퓨터 사양이 상향평준화가 되어서 크게 상관은 없을지 몰라도, 사양을 민감하게 다뤄야하고 최적화가 중요한 개발을 하고 있다면 invoke는 최대한 피하는 것이 좋다.

반응형

'Unity' 카테고리의 다른 글

Unity - Shooting Game  (0) 2022.10.23
유니티 #7 - Audio source  (0) 2022.06.05
유니티 #6 - Time.deltaTime  (0) 2022.06.04
유니티 #5 - 화면 회전 고정  (0) 2022.06.03
유니티 #4 - 게임 제작 순서  (0) 2022.06.01