シーケンサーでの時間関連のリファクタリング技術メモ

シーケンサー ツール 4.20 で実行された時間の扱いのリファクタリングに関する技術情報。

Choose your operating system:

Windows

macOS

Linux

UE4 の 4.20 リリースでは、シーケンサー内での時間の表示に関して大幅な変更が導入されました。今回の変更は、フレームの正確性が非常に重要な映画的なパイプラインおよびコンテキストのサポートを向上するためのものです。このページでは、概念的な変更に関する大まかな概要について説明し、さらにアップグレードのための最新の C++ コードの変更についても詳しく説明します。

変更内容

シーケンサー はその登場以来、 浮動小数点数 を使用して時間を 秒数 で表示していました。これにより、フレーム正確性を堅牢にサポートすることが困難で、キーフレーム位置に関するエラー、レンダリング時のエラー、不安定なカメラ カット フレーム、曖昧な評価の問題などの多くの問題の原因となってきました。エンジンの4.20 リリースでは、時間の表示に整数ティックを使用するよう変更されました。これにより、すべてではないにしても多数の問題が解決されました。

これらのティックの解釈方法は、1 秒あたりのティック数を定義するシーケンスの Tick Resolution を通じて、シーケンスごとのレベルで定義されます。このメカニズムにより、ユーザーはシーケンサー データの詳細度に関して制御が可能になります。例えば、レンダリング済みのシネマティックのマスター シーケンスであれば、プロジェクトに対して実際に希望するフレームレートを選ぶ場合がある一方で、フレームの正確性がさほど重要でないリアルタイム アプリケーションの場合、ユーザーは非常に高い解像度を選ぶことがあります。

このアプローチにより、異なるコンテキストにおいて堅牢性またはパフォーマンスを犠牲にすることなく、シーケンサーの柔軟性が大幅に高まります。4.20 より前に作成されたコンテンツはデフォルトで 60,000 fps のティック解像度にアップグレードされ、 23.976 (NTSC) 以外の共通のフレームレートに対応します。新しいシーケンスについてはデフォルトで 24,000 のティック解像度になり、 23.976 (NTSC) も含めてすべての共通の整数レートに対応します。

これらの cvars は、任意のプロジェクトで使用するデフォルト値をカスタマイズする際に有用です。

  • MovieScene.LegacyConversionFrameRate ( デフォルト:60000fps )

    • 4.20 より前に保存された UMovieScene データのデフォルトのフレーム解像度を指定します。

    • 4.20 以降で保存または再保存されたアセットには影響がありません。

  • LevelSequence.DefaultTickResolution ( デフォルト:24000fps )

    • 新しく作成されたレベル シーケンスに対するデフォルトのティック解像度を指定します。

  • LevelSequence.DefaultDisplayRate ( デフォルト:30fps )

    • 新しく作成されたレベル シーケンスに対するデフォルトの表示フレームレートを指定します。また、シーケンスがフレーム ロックとして設定されている場合のフレーム ロック フレームレートも定義します。

シーケンサーでは、浮動小数点のサブフレームを使用してキーフレーム データの評価を継続してサポートしていることに留意してください。これは、非常に低い解像度のシーケンスにおいても、実行時にスムーズな補間を実行できることを意味します。ティック解像度により制約されるのは、セクションの境界およびキーフレーム自体のみです。

任意のシーケンスに関連するすべての時間情報は、 [シーケンサー] ツールバーの [Display Rate] ドロップダウンに表示されます。また、ツールチップにはシーケンスの現在のティック解像度が表示されます。

クリックしてフルサイズ表示

このメニューでは、シーケンスの表示フレームレート、時間表示モードおよび評価タイプを変更することができます。上部レベルには、シーケンスの現在のティック解像度と互換性のある共通表示レートが表示されます。

ティック解像度と互換性のないフレームレートを使用して表示することも可能ですが、推奨はしません。

シーケンス作成後もティック解像度を変更することは可能ですが、現在の解像度の倍数ではないティック解像度にシーケンスを変換することで、セクション境界およびキーが [Advanced Options] メニューに表示される新しい解像度に四捨五入される場合があることに留意してください。

image alt text

C++ のアップグレードに関するメモ

新しい時間形式をサポートするために、多数の内部シーケンサー、MovieScene クラスおよびデータ構造に対する大規模な修正が行われました。これらの変更の規模と範囲が広大であるため、一部の API については廃止への明確な道すじを立てられないものもありました。

このセクションでは主要な変更について詳しく説明し、 4.19 から 4.20 へのコードの移行を示す例を紹介します。

変更および追加事項

  • TimeManagement モジュール:時間に関連する共通のデータ構造、操作および処理ユーティリティを提供します。

コード

説明

FFrameNumber (32 ビット)

主にコンテキストフリーのティックまたはフレーム番号を表す、タイプセーフな 32 ビットの整数。int32 以外の数値タイプからの変換はサポートしません。

FFrameTime (64 ビット)

コンテキストフリーのフレーム番号および浮動小数点サブフレームから成る時間の表示。主に評価時に使用されます。

FFrameRate (64 ビット)

整数の分子および分母 (フレーム / 秒) として保存される分数のフレームレート。

FQualifiedFrameTime (128 ビット)

秒値およびその他のフレームレートの利便性の高い変換を実現する FFrameTime および FFrameRate の構成。

FTimecode (20 バイト)

時間、分、秒およびフレーム (ドロップ フレームおよびノンドロップ タイムコードの boolean フラグを含む) を表す整数から成るタイムコードの表示

  • MovieScene Data :UMovieScene にはティック解像度および表示レートが含まれるようになり、enum 評価タイプを含む以前の Force Fixed Frame Interval 評価を支援します。UMovieScene の API に対する留意すべき変更には次が含まれます。

コード

説明

UMovieScene::GetEvaluationType()

このシーケンスの評価方法を指定する列挙型変数を取得します。

コード

説明

WithSubFrames (デフォルト)

サブフレーム補間を使用して評価します

FrameLocked

評価時にシーケンスの DisplayRate にロックして、四捨五入されたフレーム番号のみを評価し (サブフレームは評価対象外)、t.maxfps を設定します。

UMovieScene::GetTickResolution()

ムービー シーン内のすべての FFrameNumbers の解釈に使用されるティック解像度を取得します (それ以外に設定されていない場合)

UMovieScene::GetDisplayRate()

ユーザー向けの UI、ブループリント ノードおよびシーケンス プレーヤーがこのシーケンスとインターフェースする際に使用するフレームレートを取得します。また、EvaluationType が FrameLocked に設定されている場合には、t.maxfps およびロック フレームレートも定義します。

コード

説明

WithSubFrames (デフォルト)

サブフレーム補間を使用して評価します

FrameLocked

評価時にシーケンスの DisplayRate にロックして、四捨五入されたフレーム番号のみを評価し (サブフレームは評価対象外)、t.maxfps を設定します。

時間に関連するすべてのムービー シーンのデータは、所有する UMovieScene のティック解像度に基づいて、FFrameNumber を使用するよう変換済みです。これには次が含まれます。

  • UMovieSceneSection の範囲。セクションの範囲は TRange<FFrameNumber> としてのみ公開されるようになりました。また、この範囲は上限領域または下限領域が無限であることを意味しており、別の IsInfinite フラグの必要性がなくなりました。無限の範囲をサポートするセクションでは、bSupportsInfiniteRange を true に設定できるようになりました。

  • UMovieScene 再生および選択の範囲。包括的および排他的な上限領域および下限領域の両方が適切に処理されるようになりました。

  • プリロールおよびポストロールの量

  • UMovieSceneSubSection がオフセットを開始 (内部シーケンスのティック解像度内)

  • カーブ データ :既存のすべてのカーブ クラス (FRichCurve、FIntegralCurve、FNameCurve など) は、所有する UMovieScene のティック解像度で、浮動小数値ではなく FFrameNumber 時間で機能する新しいチャンネル タイプに内部で置き換えられました。時間タイプの相違のため、浮動小数点による時間表示との後方互換性はありません。レガシー クラスからの自動更新は、上記のとおりレガシー アップグレードのティック解像度を使用して、SerializeFromMismatchedTag を通じてサポートされています。

    • FRichCurve は FMovieSceneFloatChannel になりました

    • FIntegralCurve は FMovieSceneIntegerChannel になりました

    • FStringCurve は FMovieSceneStringChannel になりました

    • FNameCurve は内部では使用されません

    • FMovieSceneByteChannel (列挙型変数を含む) および FMovieSceneBoolChannel が追加されました。

以前に TCurveInterface を使用していたカスタム カーブ データ タイプは、 TMovieSceneChannelData<> GetData() メソッドを提供するのであれば、新しい FMovieSceneXYZChannel モデルに移行する作業は多くないと思われます。

ムービー シーン チャンネル

(現在は「チャンネル」と呼ばれる) カーブ データに対する必須であった最新変更内容に応じて、いくつかのエディタ コードパスが統合され、キーフレームをサポートするセクションの複製が削減されました。キーフレームとの相互作用および操作に対してエディタと実行時コードに共通言語を提供する新しいタイプ、 FMovieSceneChannelProxy が追加されました。

このため、 IKeyframeSection<> は完全に削除され、その必要性もなくなりました。汎用的なキーフレーム インタラクションをサポートするためには、キーフレームをサポートするセクションでチャンネル プロキシを適切に供給する必要のみがあります。共通のキー操作インターフェースが今ではセクション レベルではなくチャンネル レベルで存在するため、この変更によって、将来的なキーフレームを含む新しいセクション タイプの作成も非常にシンプルになります。

この新システムには、エディタのカスタマイズにやや異なるアプローチを採用するいくつかのコンポーネントが存在します。

FMovieSceneChannelProxy

UMovieSceneSection に次の通り保存します。派生タイプは、以下の例のようにこの構造にすべてのチャンネルを供給する必要があります。チャンネルは、派生タイプごとのバケットにベース FMovieSceneChannel* ごとに保存されます。このことに留意して、チャンネルの再割り当て後にはすぐにチャンネル プロキシの再作成を行う必要があります。こうすることで、古いプロキシに保存されているチャンネルを指すポインタおよびハンドルが無効化されます。

チャンネルとのすべてのインタラクションは、コンテキストに応じて FMovieSceneChannel インターフェースを通じて直接行うか、ISequencerChannelInterface を通じて行います。後者は、シーケンサー モジュール (ISequencerModule::RegisterChannelEditor) を通じてタイプごとに登録します。

これを行わないと、実行時にそのようなチャンネルの編集を試みる際にアサーションに失敗します。テンプレート化されたヘルパーは、 ADL (実引数依存の名前探索) を通じて解決される、任意のチャンネル タイプに対して単一コンセプトのオーバーローディングを許可する TSequencerChannelInterface を通じて提供されます。

これにより、ほとんどのチャンネルに対してデフォルト値が適切である場合、インターフェース全体を再実装することなく特定の動作をカスタマイズすることができます。また、これは、ISequencerSection インターフェースを手動で定義したり、エディタ内および実行時にチャンネル レイアウトを手動で定義したりすることなく、コア シーケンサー コードでチャンネル データの UI を自動的に供給できることを意味します。これにより、特に、既にサポートされているイントリンシック チャンネル データからセクションを作成する際に、カスタム セクション タイプの作成がある程度合理化されます。

ISequencerChannelInterface のデフォルトの実装関数はシーケンサー名前空間で定義されていますが、オーバーロードはチャンネルの名前空間かグローバル名前空間のいずれかに追加される必要があります。

カスタム チャンネルについては、平行配列での時間および値の保存パターンに従うことと、キーとの相互作用について TMovieSceneChannelData<T> GetData() メソッドを提供することが推奨されます。FMovieSceneChannel のほとんどのインターフェースは、TMovieSceneChannelData で呼び出し可能な関数に直接マップされています。

このプロキシ アプローチを採用することで、UI 構築およびチャンネルのキーとの相互作用に必要なすべてのデータがシーケンサー UI コードですぐに利用可能になります。

FMovieSceneChannel

すべての共通チャンネル データが相互作用可能なものを通じてインターフェースを提供します。チャンネル プロキシに追加されたすべてのチャンネルでこのタイプを実装する必要があります。

ISequencerChannelInterface

任意のチャンネルに対してシーケンサーにより必須とされている UI インタラクションおよび操作に関連する、すべてのオーバーロードへのインターフェース。各チャンネル タイプに対して ISequencerModule クラスを通じて登録されている必要があります (通常はエディタ モジュールの StartupModule メソッドにあります)。

TMovieSceneChannelTraits

拡張エディタ データなどのチャンネル タイプに対するコンパイル時の形質と、チャンネルでデフォルト値をサポートするかどうかを指定します。多くのシーケンサー UI ユーティリティは、具体的な各チャンネル タイプと相互作用するために、MovieSceneChannelTraits.h で指定されている関数オーバーロードを使用します。テンプレート化されたデフォルトのオーバーロードとチャンネル タイプに互換性がない場合は、特定のチャンネルに対する必要な関数をオーバーロードしてください。

その他のユーティリティ

ムービー シーンの範囲との作業を簡易化する目的で、ヘルパー ユーティリティがいくつか追加されました。離散型の時間ベースを使用することで、セクションの境界について合理化しやすくなりました。範囲は内部で TRange として表され、包括的、排外的およびオープンな境界をサポートします。離散型の時間ベースに対するこれらの範囲との作業を簡素化するために、MovieScene::DiscreteInclusiveLower、DiscreteExclusiveUpper および DiscreteSize を使用して、境界のさまざまな条件に一貫して対処できます。

移行ガイド

これらの変更内容の性質により、C++ で作成した独自のトラック、セクションまたはカーブが存在する場合は、移行を必要とする C++ 関連の変更があると考えられます。ユーザー独自のアップグレード事例をサポートする目的で作成された、トラック、セクション、チャンネル タイプの 移行例 プロジェクトを参照してください。

Unreal Engine のドキュメントを改善するために協力をお願いします!どのような改善を望んでいるかご意見をお聞かせください。
調査に参加する
キャンセル