スレートのスリープ タイマー / アクティブ タイマー

この機能では、新しい「アクティブ タイマー」システムをスレートに導入することで、UI を更新する必要がない場合に「スリープ」状態にすることができます。

Windows
MacOS
Linux

スレートとは「直接モード」の UI フレームワークです。つまり、フレームごとに UI 全体を作りかえます。グラフィックとアニメーションをふんだんに使用しているかなり動的なインターフェースには向いていますが、 UI に変更がない場合は無駄にプロセッサを使うだけになってしまいます。スレートでアクティブ タイマーを使用すると、 UI を更新する必要がない場合に「スリープ」状態になります。アクティブ タイマー機能は、エディタ UI での作業中に使用しますが、リアルアイム ビューポートのあるゲームの場合は UI での作業でも使用しません。

スレートは、以下の両方が所定のフレームに対して true の場合、スリープになります。

  • ユーザー アクションがない

  • アクティブ タイマーを実行する必要がない

ユーザー アクションとは、マウスの移動、クリック、キーの押下を指します。

下図は、スレート アプリケーションがフレームごとにティックする様子を表したものです。

image00.png

この図は、エディタのプロセッサの処理時間の推移を表したものです。

image01.png

アクティブ タイマー

アクティブ タイマーはウィジェットに明示的に登録されたデリゲート機能で、ユーザー アクション (タイマーの「アクティブな」性質) がない場合でも、実行時にスレート ティック / ペイント パスを引き起こします。 アクティブ タイマーは、登録が削除されるまで、実行期間によって定義された頻度で無限に実行し続けます。

オリジナルの Tick() 関数は「passive」ティックとして存在しています。これまでのようにスレートに呼び出されますが、スレートが起きている場合のみです。今後 PassiveTick() と名称変更する可能性がありますので、 Tick() は非推奨です。

アクティブ タイマーの登録は以下の手順で行います。

  1. 以下のシグネチャを使って関数を定義します。
    EActiveTimerReturnType Foo(double InCurrentTime, float InDeltaTime)

  2. それを FWidgetActiveTimerDelegate にバインドします。

  3. デリゲートと SWidget::RegisterActiveTimer() へのタイマー実行 (フレームごとの呼び出しは 0) の勘間隔をパスします。

アクティブ タイマーの登録削除は、以下の 3 通りの方法で行います。

  • EActiveTimerReturnType::Stop をデリゲートから戻す

  • SWidget::RegisterActiveTimer() から戻された`FActiveTimerHandleSWidget::UnRegisterActiveTick()` へパスする

  • アクティブ タイマーが登録されているウィジェットを廃止する

現時点ではアクティブ タイマーは全部かゼロかの状況なので、単一のアクティブ タイマーを実行するとスレートのすべてがティックされます。さらに、 ウィジェットが同時登録可能なアクティブ タイマー数に制限はありません。非常に便利な機能ですが、複製登録が発生する可能性があります。それを防ぐために、 以下のいずれかの方法で登録ステータスをトラックします。

  • アクティブ タイマーが登録されているかどうかをトラックするためにウィジェットでフラグを維持する

    • UE4 コードベースで例えば bIsActiveTimerRegistered を検索する

  • RegisterActiveTimer() から戻された FActiveTimerHandle に弱いポインタを格納し、無効な場合のみ登録する

    • UE4 コードベースで例えば TWeakPtr ActiveTimerHandle を検索する

    • メモリ節約のために、アクティブ タイマーの登録削除がどうしても必要な場合のみ、このメソッドを使用してください。

一般的なユースケース

以下の一般的なユースケースに対して、お勧めのアクティブ タイマーのセットアップ方法を説明します。

  • アクションをトリガーする場合

    • EActiveTimerReturnType::Stop を常に戻す間隔を 0 にしてアクティブ タイマーを登録します。

  • FCurveSequence で制御されないアニメーションや補間を行う場合

    1. 慣性スクロールが開始されると、間隔が 0 であるアクティブ タイマーを登録することによって、毎フレーム スクロースを更新できるようにします。

    2. 目的に到達するまで、EActiveTimerReturnType::Continue を戻し続けます。

    3. ターゲットの目的に到達したら、EActiveTimerReturnType::Stop を戻して登録削除をします。

    例となるのが、慣例のスクロールです。SScrollBox を参照してください。

  • 別のサブメニューを開いたり、タブをドッキングさせたりして、遅延後にアクションを取る場合

    • ゼロではない正の値の遅延で登録します。

    アクティブ タイマーの時間間隔は一回登録すると変更はできません。実行前に遅延をリセットするには、アクティブ タイマーを明示的に登録削除して、再登録しなければなりません。

  • アクションを定期的かつ無制限に実行する場合

    • ゼロではない正の間隔で登録して、 EActiveTimerReturnType::Continue を返し続けます。

FCurveSequence およびアクティブ タイマー

FCurveSequence の API がアップデートされ、ウィジェットのアニメート中のアクティブ ティックの登録処理が簡素化されました。 シーケンスのプレイには、アニメート元であるウィジェットへの参照が必要になりました。 シーケンスの再生中、パスされたウィジェットの代わりに空のアクティブ ティックが自動的に登録されます。 シーケンスを再生すると、シーケンスのループが指定されるようになりました。ただし、これによりアクティブ ティックが無制限に登録されるので、注意して使用してください。 ループの有無に関わらず、アクティブ ティックは Pause()JumpToStart()JumpToEnd() を呼び出すと登録削除されます。

スレート スリープのテスティング

スレートのスリープ機能には、関連するコンソール変数が 2 つあります。

  • Slate.AllowSlateToSleep は、スレートをスリープ ステートにできるかどうかを調整します。この変数はデフォルトで有効になっています。

  • Slate.SleepBufferPostInput は、スレートを起きている状態を維持させる最後のユーザー アクション後の時間を指定します。デフォルトは 0 です。スリープ システムの恒久機能ではないので、デバッグ処理のみに使用します。

目標としているスリープ状態が可能なスレートは、絶対にスリープ状態にならないスレートとは区別ができないため、スレートがスリープ状態なのか判断は難しいです。現在、これをモニターする最善の方法は、 エディタ フレームレート ([Editor Settings]>[Miscellaneous]>[Show Frame Rate and Memory]) を表示することです。フリーズすると、スレートはスリープになります。

Select Skin
Light
Dark

Welcome to the new Unreal Engine 4 Documentation site!

We're working on lots of new features including a feedback system so you can tell us how we are doing. It's not quite ready for use in the wild yet, so head over to the Documentation Feedback forum to tell us about this page or call out any issues you are encountering in the meantime.

We'll be sure to let you know when the new system is up and running.

Post Feedback