KoreanFoodie's Study

언리얼에서 Delay/Timer 기능 구현 (일정 시간이 지난 후 함수 실행) 본문

Game Dev/Unreal C++ : Dev Log

언리얼에서 Delay/Timer 기능 구현 (일정 시간이 지난 후 함수 실행)

GoldGiver 2023. 1. 3. 17:46

Delay 실행

만약 일정 시간이 지난 후 함수가 실행되길 원한다면,  FTimerHandle 을 이용해 다음과 같이 코드를 짜면 된다.

FTimerHandle myTimerHandle;
GetWorld()->GetTimerManager().SetTimer(myTimerHandle, FTimerDelegate::CreateLambda([&]()
    {
        // 내가 원하는 코드 구현
        DoSomething();
        
        // 타이머 초기화
        GetWorld()->GetTimerManager().ClearTimer(fadeOutTimerHandle);
    }), InDelayTime, false); // 반복 실행을 하고 싶으면 false 대신 true 대입

아, 참고로 FTimerHandle 은 글로벌 타이머 매니저에서 사용하며, 전역이다. 따라서 소멸자나 Finalize 함수 등에서 꼭 ClearTimer 를 이용해 타이머를 해제해 주도록 하자.

 

참고로 블루프린트에는 해당 함수가 이미 존재하긴 한다.

 

 

일정 시간 간격으로 함수 호출

다음과 같이 구현하면, '일정 시간' 동안 '일정 간격' 으로 함수를 호출시킬 수도 있다(언리얼 공식 문서 참고).

void AMyActor::BeginPlay()
{
    Super::BeginPlay();
    // RepeatingFunction 을 초당 1 회, 지금부터 2 초간 호출합니다.
    GetWorld()->GetTimerManager().SetTimer(MyTimerHandle, this, &AMyActor::RepeatingFunction, 1.0f, true, 2.0f);
}

void AMyActor::RepeatingFunction()
{
    // 이 함수를 충분히 호출했으면, 타이머를 해제합니다.
    if (--RepeatingCallsRemaining <= 0)
    {
        GetWorld()->GetTimerManager().ClearTimer(MyTimerHandle);
        // MyTimerHandle 은 이제 다른 타이머에 재사용 가능합니다.
    }
    // 여기서 어떤 작업을 합니다...
}

 

또한, 다음과 같이 타이머를 일시 정지 했다가 다시 킬 수도 있다.

void AMyActor::TimerPause()
{
    GetWorld()->GetTimerManager().PauseTimer(MyTimerHandle);
}

void AMyActor::TimerUnPause()
{
    GetWorld()->GetTimerManager().SetTimer.UnPauseTimer(MyTimerHandle);
}

FTimerManager 함수 PauseTimer 는 타이머 핸들을 사용하여 실행중인 타이머를 일시정지한다. 그러면 그 타이머는 함수 호출 실행이 막히지만, 경과 및 남은 시간은 그대로 유지된다. UnPauseTimer 는 일시정지된 타이머 실행을 재개한다.

 

 

다음 틱에 함수 호출

SetTimerForNextTick 을 사용하면 다음 틱에 함수를 호출시킬 수 있다. 사용 방법은 SetTimer 와 동일하다(매개변수만 조금 다름).

AActor* actor = GetActor();
// 타이머는 클리어 처리하고 다음 틱에 디스폰 액터를 호출
ClearTimerEvent();
GetWorld()->GetTimerManager().SetTimerForNextTick([actor]()
    {
        actor->Destroy();
    });

 

 

타이머 정보

다음과 같은 함수들을 이용해 타이머 관련 정보들을 받아올 수 있다.

/*
* 지정된 타이머가 현재 활성화되어 있고 일시정지되지 않았는지 확인 :
*/ 
// 이 무기가 다시 발사할 수 있는 대기 상태인가?
GetWorldTimerManager().IsTimerActive(this, &AUTWeapon::RefireCheckTimer);

/* 
* 타이머의 현재 속도(활성화 빈도)를 확인.타이머의 속도는 직접 변경할 수 없지만, SetTimer 를 호출하여
* 그 타이머 핸들을 해제하고 속도를 제외한 다른 부분이 같은 타이머를 새로 생성하면 됨.
* 참고로 속도란, Repeat Frequency 라고 이해하면 된다! (한 번 발사하는데 걸리는 시간 간격)
* GetTimerRate 는 타이머 핸들이 유효하지 않은 경우 -1 값을 반환 
*/
// 이 무기는 워밍업되면서 발사 속도가 변합니다. 현재 발사 대기중인지, 그렇다면 현재 발사 중간 딜레이는 얼마나 되는지?
GetWorldTimerManager().GetTimerRate(this, &AUTWeapon::RefireCheckTimer);

/*
* GetTimerElapsed 및 GetTimerRemaining 은 각각, 제공된 타이머 핸들에 연관된 타이머의 경과 및 남은 시간을 반환.
* GetTimerRate 와 마찬가지로 이 함수는 타이머 핸들이 유효하지 않은 상태인 경우 -1 을 반환
*/
// 이 무기가 다시 발사 준비 상태가 되려면 얼마나 있어야 하는지? -1 이 반환되면, 준비 완료.
GetWorldTimerManager().GetTimerElapsed(this, &AUTWeapon::RefireCheckTimer);

타이머의 경과 시간과 나머지 시간을 합하면 타이머 속도와 같아진다!

 

참고 : 언리얼 공식 문서
Comments