UE5

[UE5] 타이머

_mwmw 2023. 8. 7. 23:41

UE에서 타이머를 구현하려면 TimerManagerSetTimer()를 이용하면 된다.

 

 

SetTimer() 원형

template< class UserClass >
FORCEINLINE void SetTimer(FTimerHandle& InOutHandle, UserClass* InObj, typename FTimerDelegate::TMethodPtr<UserClass> InTimerMethod, float InRate, bool InbLoop = false, float InFirstDelay = -1.f)
{
    InternalSetTimer(InOutHandle, FTimerUnifiedDelegate(FTimerDelegate::CreateUObject(InObj, InTimerMethod) ), InRate, InbLoop, InFirstDelay);
}

FORCEINLINE void SetTimer(FTimerHandle& InOutHandle, FTimerDelegate const& InDelegate, float InRate, bool InbLoop, float InFirstDelay = -1.f)
{
    InternalSetTimer(InOutHandle, FTimerUnifiedDelegate(InDelegate), InRate, InbLoop, InFirstDelay);
}

자주 쓰이는 두 가지 형태다.

각각 함수와 델리게이트를 매개변수로 받아 호출한다.

 

 

함수를 호출

3초 뒤 Foo()를 호출하도록 해보자.

void ATimerActor::BeginPlay()
{
    Super::BeginPlay();
	
    FTimerHandle TimerHandle;

    GetWorld()->GetTimerManager().SetTimer(TimerHandle, this, &ATimerActor::Foo, 3, false);
}

void ATimerActor::Foo()
{
    // ...
}

이때 마지막 InFirstDelay 는 생략을 했는데,

InFirstDelay의 기본 값은 -1로, 0이상의 값을 넣은 경우 타이머 시작시간이 된다.

 

그럼 InFirstDelay를 이용해서 5초 뒤부터 Foo()를 1초간격으로 반복적으로 호출하도록 해보자.

void ATimerActor::BeginPlay()
{
    Super::BeginPlay();
	
    FTimerHandle TimerHandle;

    GetWorld()->GetTimerManager().SetTimer(TimerHandle, this, &ATimerActor::Foo, 1, true, 5);
}

void ATimerActor::Foo()
{
    // ...
}

이제 이 Timer친구는 ATimerActor Instance가 소멸할 때까지 우리와 영원히 함께할 것이다.

 

이번엔 조건을 만족하면 Timer가 종료되도록 해보자.

일단 FTimerHandle TimerHandle;을 헤더로 옮기자.

// TimerActor.h
FTimerHandle TimerHandle;
int32 TimerCount = 0;

// TimerActor.cpp
void ATimerActor::BeginPlay()
{
    Super::BeginPlay();
    
    GetWorld()->GetTimerManager().SetTimer(TimerHandle, this, &ATimerActor::Foo, 1, true, 5);
}

void ATimerActor::Foo()
{
    TimerCount++;
    
    if(TimerCount == 5)
    {
        GetWorld()->GetTimerManager().ClearTimer(TimerHandle);
    }
}

자, 우린 이렇게 Timer를 5번만 호출하고 미국으로 보내버렸다.

 

 

델리게이트를 호출

void ATimerActor::BeginPlay()
{
    Super::BeginPlay();

    FTimerHandle TimerHandle;

    FTimerDelegate TimerDelegate;

    TimerDelegate.BindLambda(
        []() 
        {
            // ...
        });

    GetWorld()->GetTimerManager().SetTimer(TimerHandle, TimerDelegate, 3, false);
}

FTimerDelegate를 이용하거나

 

void ATimerActor::BeginPlay()
{
    Super::BeginPlay();

    FTimerHandle TimerHandle;

    GetWorld()->GetTimerManager().SetTimer(
        TimerHandle, 
        []()
        {
            // ...
        },
        3, 
        false);
}

람다 표현식을 이용해 바로 넣을 수도 있다.