2015년 8월 17일

Slate Sleep 과 Active Timers 이용하기

저자: Dan Hertzka

Slate는 UI 프레임워크에 있어 "즉각적인 모드"로, 매 프레임마다 모든 UI를 다시 그리는데, 매우 동적인 인터페이스로 그래픽과 애니메이션이 풍부하지만, 그 특성상 UI에 변화가 없는 상황에서도 필요없는 프로세스 낭비를 하는 결과를 불러옵니다. 보통 런처와 에디터에서 자주 있는 경우입니다.

새롭게 소개해 드리는 기능으로, Slate의 “Active Timer”시스템이 있는데, UI가 업데이트 할 내용이 없는 경우 슬립 상태로 전환할 수 있습니다. 

기능 변화가 저에게 영향을 있나요? 

만약 여러분이 에디터나 런처의 UI를 만들고 있다면, 그렇습니다. 여러분이 게임 속의 실시간 뷰포트를 작업하고 계시다면, 영향을 주지 않습니다.

Slate는 언제 슬립으로 들어가나요?

주어진 프레임에서 아래 두 조건이 모두 참이면 그렇습니다.

  • 사용자의 액션이 없음
  • 실행할 활성화 된 타이머가 없음
사용자의 액션에는 어떤 것들이 있나요?

마우스 이벤트, 클릭, 그리고 키입력이 있습니다.

아래 다이어그램에서는 Slate 응용프로그램이 매 프레임마다 동작하는 것을 보여줍니다.

DH1

슬립이 동작하나요?

그렇습니다. 결과를 보여주는 그림이 이 아래에 있습니다.

DH2

active timer는 무엇을 의미하나요?

active timer는 위젯에 의해 명시적으로 레지스터 된 델리게이트 펑션으로, 사용자의 액션이 없을 때에도 Slate의 tick/paint 패스를 실행 때 일으킵니다. (그러므로 active, 능동적인 timer입니다.) Active timer는 언레지스터가 될 때 까지 무한히 주어진 실행 주기마다 실행 될 것입니다.

예전 Tick()에는 어떻게 되나요?

Tick()은 여전히 잔존할 것이지만, 수동적인 tick이라고 생각할 수 있겠습니다. 예전에는 Slate에 의해 콜이 되었지만, 지금은 Slate 가 wake 상태일 때만 될 것입니다. 그래서 이 tick의 이름으로 PassiveTick() 또는 deprecate Tick() 으로 바꿀 지에 대해서 고려중입니다.

active timer를 어떻게 임플먼트 하죠?

레지스터 하기 - 3단계
  1. 이 시그니쳐를 넣어서 함수를 정의합니다. "EActiveTimerReturnType Foo(double InCurrentTime, float InDeltaTime)".
  2. FWidgetActiveTimerDelegate 에 바인딩 시킵니다.
  3. 델리게이트와 타이머 실행주기를 SWidget::RegisterActiveTimer()에 넘겨 줍니다. (0 부터 모든 프레임 호출까지)
언레지스터 하기 - 3 단계
  1. 델리게이트로부터 EActiveTimerReturnType::Stop 을 리턴시킵니다.
  2. SWidget::RegisterActiveTimer()으로부터의 반환된 FActiveTimerHandle 을 SWidget::UnRegisterActiveTick()으로 전달합니다.
  3. active timer의 아래에 레지스터 된 위젯을 Destroy합니다.

 

중복되는 레지스터를 주의하세요!

현재, active timer는 Slate에 관해서 만약 단일 active timer가 실행되어야 한다면 모든 Slate가 tick이 되든가 아니면 전부 안 되든가 하는 양자 택일형 임플멘테이션입니다. 게다가, 동시에 한 위젯에 레지스터 가능한 active timer의 갯수에는 제한이 없습니다. 이런 특징은 아주 유용하지만, 중복되는 레지스터의 가능성을 내포하고 있습니다. 이런 문제점을 방지하기 위해서, 레지스터 된 상태를 아래 방법들 중 한 가지를 이용해서 추적하세요.

  1. active timer가 레지스터 된 위젯에 플레그를 삽입하여 추적.
    1. 예를 들어, “bIsActiveTimerRegistered“ 를 검색함.
  2. RegisterActiveTimer()에서 반환된 약한 포인터를 FActiveTimerHandle 에 저장하고 값이 invalid일 때에만 레지스터 함.
    1. “TWeakPtr<FActiveTimerHandle> ActiveTimerHandle“을 검색함.
    2. 메모리를 절약하기 위해 active timer가 명시적으로 언레지스터 되어야 할 때에만 고려하시기 바랍니다.

 

흔한 사용 예

  • 어떤 액션을 트리거하기
    • 이전에, 플래그를 저장하고 매 tick에서 true인지 봅니다.
    • 그리고 나서, active timer를 항상 EActiveTimerReturnType::Stop를 반환하는 period 0과 함께 레지스터 합니다.
  • FCurveSequence 에 의해 통제받지 않는 종류의 애니메이션이나 보간을 실행시킵니다.
    • 예제: 관성 스크롤 - SScrollBox 를 참조해 보세요
      • 관성 스크롤이 시작되면 각 프레임에서 스크롤을 하기 위해 active timer와 period 0을 레지스터 합니다.
      • 스크롤이 멈출 때 까지 EActiveTimerReturnType::Continue를 반환합니다.
      • 스크롤이 멈추면 EActiveTimerReturnType::Stop 를 반환해서 언레지스터 합니다.
  • delay 이후의 동작
    • 예제: 서로 다른 서브메뉴 열기, 탭 도킹하기
      • 양의 값 delay 레지스터 하기
      • active timer의 실행 주기는 한 번 레지스터 되면 바꿀 수 없습니다.
        • 재설정을 하기 위해서, 실행 전의 delay동안에 active timer는 반드시 명시적으로 언레지스터 후에 다시 레지스터 되어야 합니다.
  • 주기적, 무한 반복 액션 실행하기
    • 양의 값인 주기를 레지스터하고 EActiveTimerReturnType::Continue를 무한히 리턴합니다.

업데이트 된 FCurveSequence API

FCurveSequence 의 API는 위젯이 애니메이션 될 때 활성화 된 tick을 레지스터 하는 과정을 단순화하기 위해 업데이트 되었습니다. 아래는 변화된 내용입니다.

  • sequence를 재생하는 것에는 이제부터 대상 위젯의 레퍼런스가 있어야 합니다.
    • 텅빈 active tick은 sequence 플래이백 동안에 스킵된 위젯을 대신해서 자동으로 레지스터 됩니다.
  • sequence가 반복되어야 하는 지는 sequence가 재생될 때 정해질 수 있습니다.
    • 이렇게 하면 active tick을 무한반복적으로 레지스터 할 것이므로 이 부분은 조심히 다루세요!
  • 반복을 하든 안 하든, active tick은 JumpToStart(),JumpToEnd() , Pause()를 콜하면 언레지스터 될 것입니다.

전부 동작하나요?

네!... 그렇다고 봅니다. active tick 시스템은 Main 브랜치와 에디터의 모든 위젯에서 동작합니다. (찾아보면 열에 아홉은 그렇습니다. 결과물에 연결되어 있긴 하지만, 에디터 속에 두 개의 cvars가 있어서 문제가 될법한 것에 대처할 수 있습니다.

  1. Slate.AllowSlateToSleep는 Slate가 sleep 스테이트로 갈 수 있는지를 통제합니다. 기본값으로는 가능합니다.
  2. Slate.SleepBufferPostInput 는 유저의 마지막 액션으로부터 얼마큼의 시간까지 sleep으로 들어가지 않을 지를 정해 줍니다. 기본 값은 0이고 현재는 디버깅용으로만 사용되고 앞으로는 제거 될 것입니다.

 

Slate 가 sleep모드인지 어떻게 확인하죠?

Slate가 sleep 모드로 들어가지 않는 것과 확연히 비교해야 하지만 이렇다고 딱히 말씀드리기 어렵군요.

현재로써 이 것을 확인하는 가장 좋은 방법은 에디터의 프레임 레이트를 확인하는 것입니다. (에디터 개인설정 > 기타 > Show Frame Rate and Memory). 이게 멈추게 되면 Slate는 자고 있는 것입니다.

그러면 어떻게 해야 되죠?

예전에 적당히 복잡한 위젯을 만들었거나 현재 새로운 위젯을 만들고 있다면, 퍼시스턴트 실시간 뷰포트가 열리지 않은 상태에 sleep이 비활성화 된 상태에서 테스트 해 보는 것이 매우 중요합니다. (0에서 post-input 버퍼를 유지시킵니다.)

위젯이 비정상 작동하거나 위젯 업데이트에 대한 질문이 있으신 경우에는 포럼(영문)을 통해서 알려 주시기 바랍니다.