슬레이트는 '즉시 모드' UI 프레임워크로, 이는 프레임마다 전체 UI를 다시 그린다는 것을 뜻합니다. 이는 그래픽과 애니메이션이 풍부한 매우 동적인 인터페이스에는 적합하지만, UI에 변경할 것이 없을 때 불필요한 프로세서 사용을 유발합니다. 슬레이트에 활성 타이머 시스템을 사용하면 UI 업데이트가 필요하지 않을 때 슬레이트가 슬립 상태로 들어가도록 할 수 있습니다. 활성 타이머 기능은 에디터 UI 작업 시 활용해야 하며, 리얼타임 뷰포트가 있는 게임 UI 작업 시에는 활용해서는 안 됩니다.
슬레이트는 주어진 프레임에 대해 다음 두 가지 사항이 모두 true일 때마다 슬립 상태가 됩니다.
- 사용자 액션이 없음
- 실행해야 하는 활성 타이머가 없음
사용자 액션에는 마우스 움직임, 클릭 또는 키 누르기가 있습니다.
다음 다이어그램은 프레임마다 현재 슬레이트 애플리케이션이 틱되는 방식을 보여줍니다.

이 다이어그램은 슬레이트 슬립이 구현되면 에디터의 프로세서 시간이 어떻게 변하는지 보여줍니다.

활성 타이머
활성 타이머는 실행 시 슬레이트 틱/페인트 패스를 일으키는 위젯에 의해 명시적으로 등록되는 델리게이트 함수로, 사용자 액션이 없어도 실행됩니다(따라서 '활성' 속성을 띤 타이머라는 것입니다). 활성 타이머는 등록이 해제될 때까지 실행 주기에 따라 결정된 빈도로 계속해서 무한 실행됩니다.
원래의 Tick() 함수는 '패시브', 즉 비활성 틱으로 여전히 존재합니다. 전처럼 슬레이트에서 호출되지만, 슬레이트가 깨어 있을 때만 가능합니다. 향후 어느 시점에 이름을 PassiveTick()
으로 변경하고,
Tick()
은 폐기시켜 이를 명확히 반영할 것입니다.
활성 타이머를 등록하려면 다음 단계를 따릅니다.
- 다음 시그니처로 함수를 정의합니다.
EActiveTimerReturnType Foo(double InCurrentTime, float InDeltaTime)
FWidgetActiveTimerDelegate
에 바인딩합니다.- 델리게이트와 타이머 실행 주기(0은 매 프레임 호출)를
SWidget::RegisterActiveTimer()
에 전달합니다.
활성 타이머를 등록 해제하는 데 사용할 수 있는 메서드는 3가지입니다.
- 델리게이트에서
EActiveTimerReturnType::Stop
을 반환합니다. SWidget::RegisterActiveTimer()
에 의해 반환된FActiveTimerHandle
을SWidget::UnRegisterActiveTick()
에 전달합니다.- 활성 타이머가 등록된 위젯을 소멸합니다.
현재 활성 타이머는 양자택일 방식이므로, 단일 활성 타이머를 실행해야 하는 경우 모든 슬레이트에서 틱이 일어납니다. 게다가 하나의 위젯이 동시에 등록할 수 있는 활성 타이머의 수에는 제한이 없습니다. 이는 매우 유용할 수 있으나, 중복 등록의 가능성이 있기도 합니다. 이를 방지하려면 다음 방식 중 하나로 등록 상태를 추적해야 합니다.
-
위젯의 플래그를 유지하여 활성 타이머 등록 여부를 추적합니다.
- 예를 들면 UE 코드베이스에서
bIsActiveTimerRegistered
를 찾아봅니다.
- 예를 들면 UE 코드베이스에서
-
RegisterActiveTimer()
에 의해 반환된FActiveTimerHandle
로의 위크 포인터를 저장하고, 유효하지 않을 때만 등록합니다.- 예를 들면 UE 코드베이스에서
TWeakPtr<FActiveTimerHandle> ActiveTimerHandle
을 찾아봅니다. 메모리 절약을 위해서는 활성 타이머를 명시적으로 등록 해제해야 하는 경우에만 이 메서드를 사용합니다.
- 예를 들면 UE 코드베이스에서
일반적인 사용 사례
일반적인 사용 사례에서 추천하는 활성 타이머 구성은 다음과 같습니다.
-
액션 트리거 시:
- 항상
EActiveTimerReturnType::Stop
을 반환하는 활성 타이머(주기 0)를 등록합니다.
- 항상
-
FCurveSequence로 제어되지 않는 일종의 애니메이션 또는 보간 수행 시:
- 관성 스크롤이 시작되면 주기가 0인 활성 타이머를 등록하여 프레임마다 스크롤을 업데이트합니다.
- 대상에 도달하기까지
EActiveTimerReturnType::Continue
를 반환합니다. - 대상에 도달하면
EActiveTimerReturnType::Stop
을 반환하여 등록 해제합니다.
이러한 관성 스크롤의 예시는
SScrollBox
를 참조하세요. -
여러 서브 메뉴 열기, 탭 도킹 등의 딜레이 후 액션을 취하는 경우:
- 딜레이를 0이 아닌 양수로 등록합니다.
활성 타이머의 주기는 등록되면 변경할 수 없습니다. 실행 전 딜레이를 리셋하려면, 활성 타이머를 명시적으로 등록 해제하고 다시 등록해야 합니다.
-
액션을 주기적으로 무한 수행하는 경우:
- 주기를 0이 아닌 양수로 등록하고
EActiveTimerReturnType::Continue
를 계속 반환합니다.
- 주기를 0이 아닌 양수로 등록하고
FCurveSequence 및 활성 타이머
FCurveSequence
의 API가 업데이트되어 위젯이 애니메이팅되고 있을 때 액티브 틱을 등록하는 프로세스가 간소화되었습니다.
이제 시퀀스를 재생하면 애니메이팅될 위젯에 대한 레퍼런스가 필요합니다.
시퀀스 재생 중에는 전달된 위젯 대신 비어 있는 활성 틱이 자동 등록됩니다.
시퀀스의 루프 여부는 이제 시퀀스 재생 시 지정됩니다. 하지만 그렇게 하면 활성 틱이 무한 등록되므로 주의하여 사용합니다.
루프 여부와 관계없이 Pause()
, JumpToStart()
또는 JumpToEnd()
호출 시 활성 틱이 등록 해제됩니다.
슬레이트 슬립 테스트하기
슬레이트 슬립 관련 콘솔 변수는 두 가지가 있습니다.
Slate.AllowSlateToSleep
은 슬레이트가 슬립 상태에 들어갈 수 있는지 여부를 제어합니다. 현재 기본적으로 활성화되어 있습니다.Slate.SleepBufferPostInput
은 마지막 사용자 액션 이후 슬레이트가 깨어 있을 시간을 지정합니다. 디폴트값은 0입니다. 이는 슬립 시스템의 영구 기능이 아닐 수도 있으므로, 디버깅에만 사용해야 합니다.
여기서의 목표는 슬립 가능한 슬레이트를 슬립 불가능한 슬레이트와 구별하기 어렵게 만드는 것이므로, 슬레이트가 슬립 모드 상태인지 알기 어려울 수 있습니다. 현재 이를 모니터링하는 가장 좋은 방법은 에디터 프레임 레이트를 표시하는 것입니다. (에디터 세팅(Editor Settings) > 기타(Miscellaneous) > 프레임 레이트 및 메모리 표시(Show Frame Rate and Memory)) 멈춰 있으면 슬레이트가 슬립 모드인 것입니다.