참고: https://dev.epicgames.com/documentation/en-us/unreal-engine/gameplay-timers-in-unreal-engine
참고: https://milleatelier.tistory.com/104
[Unreal Engine] SetTimer() : C++ & Blueprint
게임을 만들다보면, 시간에 관계되는 이벤트를 만들어야 되는 상황이 많이 발생합니다. 개발에 정답은 없는만큼, 이러한 이벤트를 구현하는 방법 또한 여러가지가 될 수 있습니다만, 언리얼 엔
milleatelier.tistory.com
1. 현재 월드의 타이머 매니저
언리얼 엔진의 UWorld 에는 타이머를 관리하는 FTimerManager 타입의 멤버 변수가 있다.
그리고 이 TimerManager 의 SetTimer 함수를 통해 Duration, Loop 여부, 호출할 함수 등을 지정한다.
즉, 타이머 관련 로직을 구현할 때 아래와 같이 타이머 매니저를 가져와 SetTimer를 호출한다.
GetWorld()->GetTimerManager().SetTimer(...아래 이어지는 설명 참고...);
// 또는 AActor 멤버함수인 GetWorldTimerManager() 사용
GetWorldTimerManager().SetTimer(...);
2. SetTimer()
FTimerManager 의 SetTimer 함수를 엔진에서 어떻게 정의했는지 살펴보았다.
/**
* Sets a timer to call the given native function at a set interval. If a timer is already set
* for this handle, it will replace the current timer.
*
* @param InOutHandle If the passed-in handle refers to an existing timer, it will be cleared before the new timer is added. A new handle to the new timer is returned in either case.
* @param InObj Object to call the timer function on.
* @param InTimerMethod Method to call when timer fires.
* @param InRate The amount of time (in seconds) between set and firing. If <= 0.f, clears existing timers.
* @param InbLoop true to keep firing at Rate intervals, false to fire only once.
* @param InFirstDelay The time (in seconds) for the first iteration of a looping timer. If < 0.f InRate will be used.
*/
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);
}
template< class UserClass >
FORCEINLINE void SetTimer(FTimerHandle& InOutHandle, UserClass* InObj, typename FTimerDelegate::TConstMethodPtr< UserClass > InTimerMethod, float InRate, bool InbLoop = false, float InFirstDelay = -1.f)
{
InternalSetTimer(InOutHandle, FTimerUnifiedDelegate( FTimerDelegate::CreateUObject(InObj, InTimerMethod) ), InRate, InbLoop, InFirstDelay);
}
/** Version that takes any generic delegate. */
FORCEINLINE void SetTimer(FTimerHandle& InOutHandle, FTimerDelegate const& InDelegate, float InRate, bool InbLoop, float InFirstDelay = -1.f)
{
InternalSetTimer(InOutHandle, FTimerUnifiedDelegate(InDelegate), InRate, InbLoop, InFirstDelay);
}
/** Version that takes a dynamic delegate (e.g. for UFunctions). */
FORCEINLINE void SetTimer(FTimerHandle& InOutHandle, FTimerDynamicDelegate const& InDynDelegate, float InRate, bool InbLoop, float InFirstDelay = -1.f)
{
InternalSetTimer(InOutHandle, FTimerUnifiedDelegate(InDynDelegate), InRate, InbLoop, InFirstDelay);
}
/*** Version that doesn't take a delegate */
FORCEINLINE void SetTimer(FTimerHandle& InOutHandle, float InRate, bool InbLoop, float InFirstDelay = -1.f)
{
InternalSetTimer(InOutHandle, FTimerUnifiedDelegate(), InRate, InbLoop, InFirstDelay);
}
/** Version that takes a TFunction */
FORCEINLINE void SetTimer(FTimerHandle& InOutHandle, TFunction<void(void)>&& Callback, float InRate, bool InbLoop, float InFirstDelay = -1.f )
{
InternalSetTimer(InOutHandle, FTimerUnifiedDelegate(MoveTemp(Callback)), InRate, InbLoop, InFirstDelay);
}
매개변수로 다음과 같은 것을 넘겨받고 있음을 알 수 있다. (함수 매개변수 InTimerMethod 는 설명이 길어 마지막에 넣었다.)
1. FTimerHandle& InOutHandle : SetTimer 함수로 지정된 현재 타이머의 고유한 핸들 (FTimerHandle) 이다.
다른 SetTimer 호출에서 똑같은 함수 델리게이트를 등록하여도 FTimerHandle 을 달리함으로써 별개로 실행될 수 있게 하므로 필요하다.
만일 SetTimer 호출 시 인자로 전달하는 타이머핸들이 이미 다른 SetTimer 에서 지정되었던 경우, 해당 타이머를 제거하고 현재 타이머를 새로 등록한다.
2. UserClass* InObj : 타이머의 함수가 호출될 객체
3. float InRate : 타이머 시작부터 함수 호출 (firing) 까지 시간
4. bool InbLoop : 반복 여부
5. float InFirstDelay : looping 타이머의 경우, 첫 실행까지의 딜레이 별도 설정 가능
3. InTimerMethod / InDelegate / InDynDelegate / Callback : 타이머가 호출할 함수
위에 보다시피 SetTimer 는 오버로딩을 통해 호출할 함수를 여러가지 형태로 넘길 수 있도록 하고 있다.
가장 아래에서 두 번째 버전?은 함수를 입력받지 않는 버전이다.
함수를 어떤 형태로 넘길 수 있는지 위에서부터 살펴보자.
1) FTimerDelegate::TMethodPtr / TConstMethodPtr <UserClass> InTimerMethod
>> 타입이름에서 알 수 있듯이 메서드 포인터를 받고 있다. 따라서 아래와 같이 호출할 수 있을 것이다.
// 타이머 핸들 선언
FTimerHandle ThisHandle;
/////////////////////////////////
GetWorld()->GetTimerManager().SetTimer(
ThisHandle, // InOutHandle : 멤버 변수
this, // InObj : 현재 객체
&ClassName::FunctionName, // InTimerMethod : 클래스 메서드 주소값
1.0f, // InRate : 실행 주기
true, // InbLoop : 반복 여부
3.0f // InFirstDelay : 최초 실행까지 딜레이
);
2) FTimerDelegate InDelegate
델리게이트에 대해...서는 다른 게시글로 정리해보아야겠다.
--> 일단 '객체에 클래스 멤버 함수를 참조/실행하는 자료형' 으로 알고 넘어가고. IsBound 체크가 필수인 것도 주의하고.
아래와 같이 FTimerDelegate 멤버 변수를 만들어 함수를 바인드 해준 후 인자로 넘길 수 있다.
// 타이머 핸들 선언
FTimerHandle ThisHandle;
// 타이머 델리게이트 선언
FTimerDelegate ThisDelegate;
/////////////////////////////////
/////// 델리게이트에 바인드 ////////
// 1. 람다 표현식으로 함수 바인드
ThisDelegate.BindLambda([]() {
// ...
});
// 2. UObject 멤버 메서드 바인드 - weak reference
ThisDelegate.BindUObject(this, &ClassName::FunctionName);
// 3. 그 외 BindRaw (raw pointer), BindSP (shared pointer), BindStatic (raw pointer global function) 등 문서 참조
/////// SetTimer 에서 바인드된 델리게이트 호출 ////////
GetWorld()->GetTimerManager().SetTimer(
ThisHandle, // InOutHandle : 멤버 변수
this, // InObj : 현재 객체
ThisDelegate, // InDelegate : 델리게이트
1.0f, // InRate : 실행 주기
true, // InbLoop : 반복 여부
3.0f // InFirstDelay : 최초 실행까지 딜레이
);
//////// 델리게이트의 CreateLambda 를 활용할 수도 있다 ////////
GetWorld()->GetTimerManager().SetTimer(
ThisHandle, // InOutHandle : 멤버 변수
this, // InObj : 현재 객체
FTimerDelegate::CreateLambda(
[] () {
// ....
}),
1.0f, // InRate : 실행 주기
true, // InbLoop : 반복 여부
3.0f // InFirstDelay : 최초 실행까지 딜레이
);
3) FTimerDynamicDelegate InDynDelegate
위와 비슷한데, 다이내믹 델리게이트는 serialization 이 가능, 일반 델리게이트보다 느림
다이내믹 델리게이트가 무엇인지는 여기에서...
https://dev.epicgames.com/documentation/ko-kr/unreal-engine/dynamic-delegates-in-unreal-engine
https://darkcatgame.tistory.com/66
UE4 C++ Delegate 정리 & 샘플 프로젝트
개인적으로 UE4 C++에서 Delegate를 사용할 때 처음에 굉장히 에러를 많이 겪었습니다, 그래서 이번 포스팅은 UE4 C++에서 Delegate를 사용하는 방법에 대해 정리하고 샘플프로젝트도 만들었습니다. https
darkcatgame.tistory.com
4) TFunction<void(void)>&& Callback
TFunction 은 그냥 언리얼 엔진의 람다 표현식이라고 보면 된다고 한다.
https://forums.unrealengine.com/t/can-someone-give-me-code-snippet-of-how-to-use-tfunction/138531
Can someone give me code snippet of how to use TFunction?
FWebBrowserWindow::GetSource(TFunction<void(const FString&)> Callback) const; I need to use GetSource to get html content, does anyone know how to input a correct TFunction ? Thanks. 🙁
forums.unrealengine.com
https://forums.unrealengine.com/t/tfunction-as-parameter-syntax-problem-solved/654329
TFunction as parameter syntax problem [SOLVED]
Hi all, How does the syntax work for providing a function argument of the type TFunction given the following situation: // in file 1 void UMyObject::StaticFunction(TFunction<void(AActor*)> functionAsParam) { functionAsParam(GetSomeActor()); } // in file 2
forums.unrealengine.com
GetWorld()->GetTimerManager().SetTimer(
ThisHandle, // InOutHandle : 멤버 변수
this, // InObj : 현재 객체
[]() {
}, // Callback : TFunction
1.0f, // InRate : 실행 주기
true, // InbLoop : 반복 여부
3.0f // InFirstDelay : 최초 실행까지 딜레이
);
/// 또는 아래와 같이 람다 표현식을 변수화하고 인자로
TFunction<Type(Type)> FunctionName = []() {
//...
};
// 또는 아래와 같이 멤버 메서드를 TFunction 변수화하여 인자로
TFunction(Type(Type)> FunctionName = &ClassMethodName;
한줄평
언리얼 엔진의 함수 델리게이트에 대해 더 알아보아야겠다...ㅋ
'언리얼_엔진_게임개발_공부 > 언리얼 C++' 카테고리의 다른 글
[언리얼/C++] FMath:: Lerp 함수 활용 / Linear Interpolation 선형보간법 (0) | 2025.02.03 |
---|---|
[언리얼/C++] OnComponentBeginOverlap - 액터 오버랩 시 함수 호출 / FindPlayerStart - 게임모드의 플레이어스타트 가져오기 (0) | 2025.01.27 |
[언리얼/C++] 열거형 - UENUM / 언리얼 엔진의 EAxis (0) | 2025.01.23 |
[언리얼/C++] 비트마스크 Bitmask / TryFindType, UnknownFunction 경고 해결 (1) | 2025.01.21 |
[언리얼/C++] Tick 함수로 메쉬 스케일 변경 (커졌다 작아졌다 하게) (0) | 2025.01.21 |