Large World Coordinates プロジェクトの変換ガイドライン

このドキュメントは、精度の損失を最小限に抑えながら UE4 プロジェクトを UE5 に変換するためのガイドラインです。

Large World Coordinates (LWC) は、既存のプロジェクトにシームレスに取り込めるよう設計されています。 Unreal Engine 5 へのプロジェクトのインポート後にこのガイドを参考にして変換することができますが、その際にいくつかの問題が生じる場合があります。ソース コードでは、バリアント タイプに、元の Unreal Engine 4 (UE4) の名前と一致する倍精度タイプをデフォルトとする typedef エイリアスが含まれています。既存のコードは、倍精度タイプをサポートするよう自動的に再コンパイルされます。

エイリアス化されたタイプの変更点

将来における互換性のために、可能な場合には常に FVector エイリアスを使用し、特定のタイプをどうしても確保しなければならない場合のみに、明示的な FVector3f または FVector3d タイプにフォールバックすることをお勧めします。

以下の表には、バリアントに変換されたタイプが示されています。

デフォルト (倍精度バリアント エイリアス)

浮動小数バリアント

倍精度バリアント

FVector

FVector3f

FVector3d

FVector2D

FVector2f

FVector2d

FVector4

FVector4f

FVector4d

FMatrix (FScaleMatrix,FQuatRotationTranslationMatrix, and more.)

FMatrix44f

FMatrix44d

FPlane

FPlane4f

FPlane4d

FQuat

FQuat4f

FQuat4d

FRotator

FRotator3f

FRotator3d

FTransform

FTransform3f

FTransform3d

FBox

FBox3f

FBox3d

FBox2D

FBox2f

FBox2d

FSphere

FSphere3f

FSphere3d

FBoxSphereBounds

FBoxSphereBounds3f

FBoxSphereBounds3d

FCapsuleShape

FCapsuleShape3f

FCapsuleShape3d

FDualQuat

FDualQuat4f

FDualQuat4d

FRay

FRay3f

FRay3d

将来における互換性を維持するために、どうしても必要な場合を除き、バリアント タイプを使用することはお勧めしません。代わりに、上記のエイリアスにある元のバージョンを使用して、特定のタイプを確保する必要がある場合のみに、明示的な浮動小数 (単精度) および倍精度タイプを使用してください。

異なるバリアント間でキャストする場合は、これを明示的に行う必要があります。次に例を挙げます。

    FVector Vec(1.0, 2.0, 3.0); 

    FVector3f AsFloat = FVector3f(Vec);

    FVector3f AsFloat = Vec;    // Will fail to compile.

倍精度タイプに対する FMath サポート

倍精度タイプをサポートするように FMath の機能が拡張されました。これには、新しいタイプでの通常の数学演算に対するサポートも含まれます。

また、これには「UnrealMathSSE.h/UnrealMathNeon.h」ディレクトリにある VectorRegister からのベクター化サポートも含まれています。これにより、VectorRegister4fVectorRegister4d タイプが追加されます。

ラージ ワールドをテストする

UE5 のラージ ワールドはベータ版であるため、デフォルトの WORLD_MAX サイズはUE4 の WORLD_MAX サイズ (21 km) で維持され、ワールドの境界チェックはデフォルトで有効になります。ラージ ワールドのスケールを試すためのオプションが 2 つあります。

WorldSettings クラスにアクセスして bEnableLargeWorlds ブール値を true に設定することで、境界チェックを無効にすることができます。

    AWorldSettings::bEnableLargeWorlds = true

これにより、WORLD_MAX の値をおよそ 21 km に維持して、Unreal Engine 5.0 初期リリースでの試用における安定性を高めることができます。

また、その代替手段として、より大きなワールド境界を可能にするために、UE_USE_UE4_WORLD_MAX のグローバル値を次のように設定できます。

UE_USE_UE4_WORLD_MAX=0 

これにより、WORLD_MAX の値がおよそ 8,800 万 km にまで広がります。

この数値は、Unreal Engine の将来のリリースで変更される可能性があります。また、安定性の問題が発生する可能性がありますが、Unreal Eigne 5 の開発を通じて継続的に最適化される予定です。

プロジェクトが 22km の UE4 WORLD_MAX マクロに依存している場合、 UE_USE_UE4_WORLD_MAX=1 マクロでビルドすることにより、そのバージョンに戻すことができます。あるいは、プロジェクトコードを更新して UE_OLD_WORLD_MAX マクロと同等のものを適宜使用することも可能です。OLD (UE4)、LARGE (UE5)、HUGE_DISTANCE (精度制限) の定義一覧は、 EngineDefines.h を参照してください。

コードのコンパイル エラー

次は、コンパイル エラーをいくつかのカテゴリに分類し、推奨される解決策をそれぞれまとめたものです。

バリアント タイプの前方宣言

前方宣言ステートメントを記述する際は UE_DECLARE_LWC_TYPE マクロを使用してください。

例えば、以下の代わりに

struct FVector; 

FVector を以下として宣言します

UE_DECLARE_LWC_TYPE (Vector, 3);

タイプごとの適切な UE_DECLARE_LWC_TYPE の使用例については、「Engine/Source/Runtime/Core/Public/CoreFwd.h」を参照してください。

generated.h または CoreMinimal.h を含むファイルについては、バリアント タイプの前方宣言は必須ではありません。

エラー:C2027/C2371

FVector またはそれ以外のバリアント タイプについてプロジェクトで C2027/C2371 エラーが発生する場合は、構造体としてコード内に含まれる当該タイプの前方宣言が原因であることがほとんどです。

警告:「Arguments cause function resolution ambiguity (引数による関数解決の曖昧さ)」

バリアント タイプ、浮動小数点値、定数引数が混在し、複数の引数を含む FMath 関数を呼び出した際に、上記のような警告が表示される場合があります。

これはプログラム内で生じている精度の損失を示している可能性があるため、関数解決の曖昧さを示す警告は無視しない ことが重要です。

精度に関するエラーは、明示的なテンプレート引数を渡すか、一致しないタイプをキャストするか、希望のタイプと一致するよう定数を変更することで修正できます。

次に例を挙げます。

    FMath::Max(MyVector.X, double(MyFloat));

浮動小数と倍精度バリアント タイプ間の変換には明示的なキャストが必要

コード内で浮動小数タイプと倍精度バリアント タイプとの間で変換を行う際は、精度やパフォーマンスに関する問題を回避するために、明示的なキャストが必要になります。

例えば、FVector4 を必要とする関数に FVector3f を渡す場合は、このことを考慮する必要があります。FVector3fFVector にキャストする必要があるため、これによって、変換を完了するために FVector から FVector4 への暗黙的なキャストが有効になります。

内部システムでは、明示的なキャストが似たタイプに適用されます。例えば、Chaos FVec3FVector3f に適用されます。

シェーダー パラメータ

GPU では倍精度のパラメータはサポートされません。そのため、FVectorFVector2DFVector4FMatrix はネイティブ コード内の SHADER_PARAMETER 宣言でサポートされなくなりました。これらは、対応するタイプの浮動小数バリアントにそれぞれ切り替える必要があります。

ランタイム チェックの失敗

次のようにランタイム チェックが失敗することがあります: Unexpected element array size in TArray::BulkSerialize (TArray::BulkSerialize における予期せぬ要素配列サイズ)

これは、倍精度バリアントに自動変換されたタイプを含む構造体を一括でシリアル化したことが原因で発生することがあります。これは、アーカイブ バージョンに応じて bForcePerElementSerialization パラメータを追加することで修正できます。

MyArray.BulkSerialize(Ar, Ar.UEVer() < EUnrealEngineObjectUE5Version::LARGE_WORLD_COORDINATES); 

アーカイブに最新のバージョンが含まれることを確認してください。

精度の問題

移行された UE4 プロジェクトで LWC タイプのコンポーネントを倍精度タイプに変換すると、特にこれらのコンポーネントが浮動小数であることを想定して書かれたコードの場合は、精度の問題が発生することがあります。アップグレード後に、このような問題の可能性についてコードを監査することをお勧めします。

安全でないタイプキャスト警告を有効にする

次に、安全でないタイプキャスト警告をプロジェクトで受け取るようにするためのいくつかの方法を示します。

モジュールの使用

プロジェクトの「build.cs」ファイルに次を追加します。

UnsafeTypeCastWarningLevel = WarningLevel.Warning;

これによって大規模なコードベースで多数の警告が生成される可能性がありますが、精度の損失につながる状況を検出して修正する上で貴重な情報となります。

現在、一部のエンジン ヘッダ ファイルでは安全でないタイプキャスト警告が生成されますが、今後のリリースで修正される予定です。

単一のファイルまたはコード ブロックの使用

次のマクロにより、安全でないタイプキャスト警告の有効/無効を切り替えることができます。

マクロ

説明

PRAGMA_FORCE_UNSAFE_TYPECAST_WARNINGS

モジュールの設定にかかわらず、この時点を過ぎると安全でないタイプキャストによってエラーが生成されます。

PRAGMA_DISABLE_UNSAFE_TYPECAST_WARNINGS

モジュールの設定にかかわらず、この時点を過ぎると安全でないタイプキャストが無視されます。

PRAGMA_RESTORE_UNSAFE_TYPECAST_WARNINGS

FORCE/DISABLE ブロックのエンド マーカーです。モジュールで設定された動作に戻ります。ブロックが正しく閉じられないと CheckBalancedMacros 自動化スクリプトが失敗します。

Type コンポーネントのコピーの格納時に精度の損失がないことを確認する

Type コンポーネントに直接アクセスするコードには、精度の損失を回避するためにリファクタリングが必要な場合があります。精度のエラーは無効なコード実行につながる可能性があります。次に例を示します。

const float X = MyVector.X; 

// MyVector.X may be more precise than we expect now.
//SMALL_NUMBER == 1e-8 (0.00000001)
// Double to float conversion can introduce precision error at as few as 6 significant digits.

if(FMath::Abs(X - OtherVector.X) > SMALL_NUMBER)
{
 // If MyVector.X and OtherVector.X are identical we wouldn't expect to get in here.
}

MyVector.X の高精度な倍精度値については、XOtherVector.X デルタとの差異が十分に大きいため、コードがこのパスに従うようになります。

プロジェクトを UE4 の浮動小数タイプによる 10.5 km の境界制限を超えて拡張するよう計画している場合は、原点からより遠くに移動するため、これによってリスクが大幅に高まります。

float X = MyVector.X; 

X += 0.5f;

MyVector.X = X; // Precision loss.

移行したプロジェクトで Large World Coordinates の使用を予定している場合は、このような精度のエラーについてコードベースを監査する必要があります。

LWC タイプでは、FReal エイリアスがそのベースのコンポーネント タイプ (浮動小数または倍精度) に公開されます。FReal を基本的なタイプの代わりに使用することで、そのタイプが将来変更された場合でも精度の問題を確実に回避できます。次に例を示します。

FVector::FReal ReallyADoubleNow = FMath::Cos(MyVector.X);

新しいアプローチでは、コードベース全体で浮動小数タイプを倍精度タイプに更新します。

double ReallyADoubleNow = FMath::Cos(MyVector.X);

精度の損失を回避するために、Type コンポーネントに直接アクセスするコードにはリファクタリングが必要な場合があります。

移行した UE4 プロジェクトで浮動小数タイプによる境界 (原点からおよそ 10.5 km) を維持する予定であれば、精度の損失が生じる可能性はありますが、プロジェクトには悪影響が及ばない場合もあります。

バリアント タイプの一括シリアル化

移行したプロジェクトについては、デフォルト コア タイプ (FVector) の配列の一括シリアル化はデフォルトで無効になっています。エンジンでは、まずそれぞれのベクター コンポーネントを浮動小数タイプとしてロードして、その後に倍精度タイプに変換する必要があります。影響を受けるアセットを再び保存すると、そのアセットは倍精度タイプとして記述されて、一括シリアル化が再び可能になります。 バリアント タイプを含む構造体を一括シリアル化する場合は、浮動小数バリアントを使用できるようにそれを変換するか、BulkSerialize 呼び出し内でインスタンスごとのシリアル化を強制実行して TCanBulkSerialize サポートを無効にする必要があります。

コア タイプのメモリ消費の削減

プロパティ指定子によってマーキングされたシリアル化済みのコア タイプでは、倍精度バリアントと浮動小数バリアントの切り替えを自動的に認識します。これにより、浮動小数に随時切り替えることで、浪費されたメモリを遡及的に解放できるようになります。

ブループリント

UE5 では、すべてのブループリント浮動小数タイプが、単精度および倍精度の両方で機能するよう変更済みの浮動小数タイプによって表されます。つまり、これはブループリントが自動的に LWC スケールをサポートすることを意味しています。ブループリントにおける明示的な浮動小数 / 倍精度のサポートを取り除いた結果として、インポートされた UE4 ブループリント プロジェクトに含まれるすべての浮動小数または倍精度タイプは新しいタイプに昇格されます。

ソース コード インターフェース

ソース コードで浮動小数と倍精度の各タイプを公開できるようになりました。Unreal Header Tool (UHT) では、コード内のブループリントによるアクセスが可能な浮動小数点タイプを、適切な単精度 (C++ float) または倍精度 (C++ double) サブタイプを含むブループリント浮動小数と解釈するため、あらゆるブループリント ノードで提供されるいずれかの精度の浮動小数値の自動変換が可能になります。 浮動小数点という用語については注意が必要です。

ブループリントにおける浮動小数は単精度と倍精度の浮動小数のいずれかを指す一方で、C++ ではそれを明示的に表す必要があります。 「浮動小数 (Float)」は特に単精度の浮動小数を表し、「倍精度 (Double)」は倍精度の浮動小数を表します。Unreal Header Tool では、プロパティまたは関数のパラメータに対して両方のタイプを有効とみなします。タイプが「浮動小数」または「倍精度」の場合、ブループリントではそれを単一の「浮動小数」タイプとして扱いますが、その浮動小数が単精度または倍精度であるかが示されます。

single-float-precision-node

ブループリントを使用するユーザーの観点からは、単精度と倍精度のタイプに違いはなく、明示的なキャスト ノードなしにこれらのピンを互いに接続できます。それでも Unreal Engine では、これらのインスタンスにおいて、変換の絞り込みか拡大のいずれかを実行しなければならない場合があります。ブループリント コンパイラでは、潜在的なあらゆる浮動小数点の変換についてブループリント グラフを自動分析します。変換が検出された場合は、コンパイアラによって、ベースとなるコードにキャスト演算が自動的に挿入されます。これはコンテナでも同様に機能します。

デベロッパーは、Large World Coordinates のメリットを得るために、以前に作成したブループリント コンテンツに対して特別な修正を行う必要はありません。Unreal Engine により、倍精度を使用するように浮動小数ピンがデフォルトで自動変換されます。ネイティブ C++ コード内に、単精度の浮動小数値に使用されるピンが存在する場合は、Unreal Engine により、これらのピンが引き続き単精度の浮動小数を表すことが保証されます。これには、ネイティブ C++ プロパティ、関数パラメータ、そしてネイティブ C++ デリゲートにバインドされているあらゆるブループリント関数のパラメータが含まれます。

UFUNCTION プロパティ指定子の予期される浮動小数値を公開する

ブループリント浮動小数値はより低精度の浮動小数にキャストされるため、UFUNCTION プロパティ指定子でマーキングされた、浮動小数値データを含むあらゆるメソッドには精度を低下させるリスクが伴います。既存の UFUNCTION プロパティをすべて監査することが重要です。これにより、パラメータまたは戻り値を倍精度値に切り替えることが、将来的に精度に関する問題を回避する上で必要であるかどうかを判断しやすくなります。浮動小数と倍精度のタイプの切り替えはいずれの方向も安全で、いつでも実行できます。

これは、コードで構築済みまたは公開済みのあらゆる K2 ノードに適用されます。

プラグイン - 公開済みプラグインのデベロッパーに向けたガイドライン

ラージ ワールドをサポートするように既存のプラグインを変換する場合は、プラグインで精度の損失が発生しないよう十分に注意してください。プライグインのコア タイプ コンポーネントを更新する際は、本ドキュメントの「精度の問題」セクションに記載されている全般的なガイドランを参考にすることをお勧めします。

完全なワールド空間を必要とするプラグイン

プラグインには、完全なワールド空間への変換を必要とするものがあります。それらに対しては、倍精度を使用するようにベースのタイプを変換します。エンジンはプラグインを UE5 に変換するプロセスのほとんどに自動的に対応しますが、デベロッパーは結果を浮動小数として格納することで、コードで精度のエラーが発生していないことを確認する必要があります。

例えば、UE4 でワールド座標を表す FVector は、UE5 では倍精度タイプにアップグレードされていますが、使用するプラグインがコンポーネント レベルでコア タイプにアクセスする場合は、精度を確実に維持するためにコードのリファクタリングが必要になることがあります。

ワールド空間の原点のみのプラグイン

一部のプラグインは浮動小数スケールのローカル空間のみで使用され、エンジンに依存することで、ワールド空間の原点で結果をレンダリングします。このような場合は、プラグインによって内部で使用されるコア タイプを浮動小数バリアントに変換することを検討してください。こうすることで、倍精度に使用していたメモリを解放できます。

UE4 と UE5 の両方をサポートする

両方のエンジンのバージョンをターゲットとするプラグインは、ソースでコンパイルするコード、または個別のバイナリ パッケージとして配布する必要があります。UE4 ではコア タイプ バリアントはサポートされないため、UE5 に対応したコードがデフォルトのコア タイプのみを使用することを確認するか (UE4 では浮動小数として、UE5 では倍精度としてコンパイル)、プラグインの UE4 バージョンと UE5 バージョン向けに個別のソース コードを提供する必要があります。

コア タイプのコンポーネントを使って中間計算に正しい精度が使用されることを確実にするには、自動 C++ 宣言か倍精度のいずれかを使用してそれらを処理できます。

LWC レンダリングの概要

Large World Coordinates とともに新しい HLSL タイプが導入されました。これは「LargeWorldCoordinates.ush」ファイルに含まれています。シェーダー コードを UE5 に変換する方法の詳細については、「LWC レンダリングに関するドキュメント」を参照してください。

タグ