언리얼 엔진에서 타이머와 틱 함수는 시간 기반 이벤트와 주기적인 업데이트를 처리하는 데 중요한 역할을 합니다.
이 절에서는 이들의 개념과 C++에서의 활용 방법을 살펴보겠습니다.
타이머 시스템
타이머의 종류
단일 실행 타이머
반복 실행 타이머
지연 실행 타이머
타이머 설정 방법
// 단일 실행 타이머
FTimerHandle TimerHandle;
GetWorld ()-> GetTimerManager (). SetTimer (TimerHandle, this , & AMyActor ::MyTimerFunction, 2.0f , false );
// 반복 실행 타이머
GetWorld ()-> GetTimerManager (). SetTimer (TimerHandle, this , & AMyActor ::MyRepeatingFunction, 1.0f , true );
// 지연 실행 타이머
FTimerDelegate TimerDelegate;
TimerDelegate . BindUFunction ( this , FName ( "MyDelayedFunction" ), Param1, Param2);
GetWorld ()-> GetTimerManager (). SetTimerForNextTick (TimerDelegate);
Copy
타이머 관리 기법
// 타이머 일시 정지
GetWorld ()-> GetTimerManager (). PauseTimer (TimerHandle);
// 타이머 재개
GetWorld ()-> GetTimerManager (). UnPauseTimer (TimerHandle);
// 타이머 중지 및 제거
GetWorld ()-> GetTimerManager (). ClearTimer (TimerHandle);
// 남은 시간 확인
float RemainingTime = GetWorld ()-> GetTimerManager (). GetTimerRemaining (TimerHandle);
// 타이머 활성 여부 확인
bool bIsActive = GetWorld ()-> GetTimerManager (). IsTimerActive (TimerHandle);
Copy
틱(Tick) 함수
틱 함수의 역할
틱 함수는 매 프레임마다 호출되어 지속적인 업데이트가 필요한 로직을 처리합니다.
커스텀 틱 함수 구현
UCLASS ()
class MYGAME_API AMyActor : public AActor
{
GENERATED_BODY ()
public:
AMyActor ();
virtual void Tick ( float DeltaTime ) override ;
private:
float AccumulatedTime;
};
AMyActor :: AMyActor ()
{
PrimaryActorTick . bCanEverTick = true ;
AccumulatedTime = 0.0f ;
}
void AMyActor :: Tick ( float DeltaTime )
{
Super :: Tick (DeltaTime);
AccumulatedTime += DeltaTime;
if (AccumulatedTime >= 1.0f )
{
UE_LOG (LogTemp, Log, TEXT ( "One second has passed!" ));
AccumulatedTime -= 1.0f ;
}
}
Copy
틱 함수의 성능 영향과 최적화 전략
조건부 틱 활성화
void AMyActor :: SetShouldTick ( bool bShouldTick )
{
SetActorTickEnabled (bShouldTick);
}
Copy
틱 간격 조정
PrimaryActorTick . TickInterval = 0.1f ; // 0.1초마다 틱
Copy
틱 기능 컴포넌트화
UCLASS (ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class MYGAME_API UMyTickComponent : public UActorComponent
{
GENERATED_BODY ()
public:
UMyTickComponent ();
virtual void TickComponent ( float DeltaTime , ELevelTick TickType , FActorComponentTickFunction * ThisTickFunction ) override ;
};
Copy
타이머와 틱 함수를 활용한 게임플레이 로직 구현
시간 기반 이벤트 처리
void AMyGameMode :: StartRound ()
{
GetWorld ()-> GetTimerManager (). SetTimer (RoundTimerHandle, this , & AMyGameMode ::EndRound, RoundDuration, false );
}
void AMyGameMode :: EndRound ()
{
// 라운드 종료 로직
UE_LOG (LogTemp, Log, TEXT ( "Round Ended!" ));
}
Copy
프레임 독립적인 업데이트 구현
void AMyActor :: Tick ( float DeltaTime )
{
Super :: Tick (DeltaTime);
// 프레임 독립적인 이동
FVector NewLocation = GetActorLocation () + (Velocity * DeltaTime);
SetActorLocation (NewLocation);
}
Copy
타이머와 틱 함수 사용 시 주의사항
타이머 핸들 관리: 객체 소멸 시 활성 타이머 제거
void AMyActor :: EndPlay ( const EEndPlayReason :: Type EndPlayReason )
{
Super :: EndPlay (EndPlayReason);
GetWorld ()-> GetTimerManager (). ClearAllTimersForObject ( this );
}
Copy
틱 함수 과다 사용 주의 : 필요한 경우에만 틱 활성화
긴 실행 시간 작업 회피 : 틱 함수에서 무거운 연산 피하기
타이머와 틱 함수의 효과적인 조합
주기적인 상태 체크에 타이머 사용, 연속적인 업데이트에 틱 함수 사용
void AMyActor :: BeginPlay ()
{
Super :: BeginPlay ();
GetWorld ()-> GetTimerManager (). SetTimer (StatusCheckTimerHandle, this , & AMyActor ::CheckStatus, 5.0f , true );
}
void AMyActor :: Tick ( float DeltaTime )
{
Super :: Tick (DeltaTime);
UpdatePosition (DeltaTime);
}
void AMyActor :: CheckStatus ()
{
// 5초마다 상태 체크
}
void AMyActor :: UpdatePosition ( float DeltaTime )
{
// 매 프레임 위치 업데이트
}
Copy
타이머를 사용한 틱 함수 최적화
void AMyActor :: BeginPlay ()
{
Super :: BeginPlay ();
GetWorld ()-> GetTimerManager (). SetTimer (TickTimerHandle, this , & AMyActor ::CustomTick, 0.1f , true );
SetActorTickEnabled ( false ); // 기본 틱 비활성화
}
void AMyActor :: CustomTick ()
{
// 0.1초마다 실행되는 커스텀 틱 로직
}
Copy
Best Practices
타이머 함수 네이밍 규칙
void AMyActor :: OnHealthRegenTick ()
{
// 'On' 접두사와 'Tick' 접미사 사용
}
Copy
틱 함수 내 프로파일링
void AMyActor :: Tick ( float DeltaTime )
{
Super :: Tick (DeltaTime);
SCOPE_CYCLE_COUNTER (STAT_MyActorTick);
// 틱 로직
}
Copy
타이머와 델리게이트 조합
DECLARE_DYNAMIC_MULTICAST_DELEGATE (FOnTimerEventSignature);
UPROPERTY (BlueprintAssignable, Category = "Events" )
FOnTimerEventSignature OnTimerEvent;
// 타이머 설정
GetWorld ()-> GetTimerManager (). SetTimer (TimerHandle, FTimerDelegate :: CreateUObject ( this , & AMyActor ::OnTimerFired), 1.0f , false );
void AMyActor :: OnTimerFired ()
{
OnTimerEvent . Broadcast ();
}
Copy
조건부 틱 함수 최적화
void AMyActor :: Tick ( float DeltaTime )
{
Super :: Tick (DeltaTime);
if (bShouldUpdate)
{
PerformUpdate (DeltaTime);
}
}
Copy
타이머와 틱 함수는 언리얼 엔진에서 시간 기반 이벤트와 주기적인 업데이트를 처리하는 강력한 도구입니다. 타이머는 지연 실행, 반복 실행 등 다양한 시나리오에 활용할 수 있으며, 틱 함수는 매 프레임 업데이트가 필요한 로직에 적합합니다. 그러나 이들을 효과적으로 사용하기 위해서는 성능 영향을 항상 고려해야 합니다.
타이머는 정확한 시간 간격이 필요한 경우나 비교적 긴 주기의 이벤트에 적합하며, 틱 함수는 연속적이고 빈번한 업데이트에 사용됩니다. 두 메커니즘을 적절히 조합하여 사용하면, 효율적이면서도 정확한 시간 기반 게임플레이 로직을 구현할 수 있습니다.
성능 최적화를 위해 불필요한 틱 함수 호출을 줄이고, 타이머의 정확한 관리와 해제를 신경 써야 합니다. 프레임 독립적인 업데이트 로직을 구현하여 다양한 하드웨어 환경에서 일관된 게임플레이를 제공하는 것도 중요합니다.
마지막으로, 디버깅과 프로파일링 도구를 활용하여 타이머와 틱 함수의 성능 영향을 지속적으로 모니터링하고 최적화하는 것이 좋습니다. 이를 통해 원활하고 효율적인 게임 실행을 보장할 수 있습니다.