BLOGブログ

2022.12.07UE5UE/ C++UE/ Landscape

[UE5] カスタムランドスケープインポータのプラグインの作成

執筆バージョン: Unreal Engine 5.1

 

こんにちは。エンタープライズエンジニアの方井です。

Landscapeについて調べたことがある方は、以下のページを目にしたことがあるのではないでしょうか?

Unreal Engine でのカスタム ランドスケープ インポータの作成 | Unreal Engine ドキュメント

一度でもカスタムランドスケープインポータを作成したことある方であれば「そうそう、簡単に言えばその通り!」と感じますが、そうでない方はページに記載通り、ビルトインされていて豊富な機能を持つ.PNG実装や.RAW実装を見ながら必要な実装を探ることとなります。

そこで今回は、とても簡素なカスタムランドスケープインポータのプラグインを作成しながらこのページを理解しようと思います。

※注意:エクスポートには対応しません。

今回のプラグインを作成することで、以下の2つの単純なテキストファイルを読み込んで、図のようなそれぞれ小さなLandscapeを作成することができます(わかりやすいようにPixelNormalを表示するMaterialを割り当てています)。

Format1, 2


 

1. プラグインを作成する

ドキュメント通り、プラグインによるカスタムランドスケープインポータを実現するため、自作プラグインを作成します。

EditからPlugins画面を開き、Addボタンで新規プラグインを作成します。

PluginウィンドウでAddをクリック

New Plugin画面では、Blankテンプレートを選択し、詳細情報を記載していきます。

  • Author:実装者
  • Description:プラグインの説明
  • Author URL:実装者を示すURL
  • Is Beta Version:ベータ版か否か(trueの場合、プラグインを有効にした際にベータ版であることを示すダイアログが表示されます)

また、このプラグインではコンテンツを含む予定は無いため、Show Content Directoryをfalseにします。

New Plugin画面での一例

Create Pluginボタンを押すことで、プロジェクトのPluginsフォルダにプラグインが生成されます。

 

2. プラグインの設定を行う

作成したプラグインの.upluginファイルを編集します。

Modulesにある<Module名>のTypeを”Runtime”から”Editor”へ、LoadingPhaseを”Defalut”から”PostEngineInit”へ変更します。(おそらくModule名とプラグイン名は同一かと思います)

変更する理由(Type)

このプラグインはLandscapeを作成する際に利用される機能を提供します。UE5.0.3時点ではRuntime中にLandscapeを作ることはできないため、このプラグインがPackageに含まれないようEditorのみであることを明示する必要があります。

変更する理由(LoadingPhase)

LandscapeEditorのModuleの初期化が終わった後にこのプラグインの初期化を走らせたいからです。

この変更が無ければ、このプラグインが初期化時に参照するLandscapeEditorのModuleがロードできません。(ロードの順番は未定義なので、通る場合もあります)

 

3. Moduleの設定を行う

作成したプラグインにあるModuleの.Build.csファイルを編集します。

PublicDependencyModuleNamesに”LandscapeEditor”を追加します。

これにより、今回必要な”LandscapeEditor”でPublic公開されている機能を利用することができます。

 

4. ILandscapeHeightmapFileFormatを実装するオブジェクトを作成する

ILandscapeHeightmapFileFormatはインターフェースクラスのため、C++クラス ウィザードを利用して継承クラスを作成することはできません。

プラグインのSource/<Module名>/Privateに直接ファイルを作成していきます。

ヘッダファイルを以下のように記述します。

まず変数ですが、対応する拡張子、GetInfo関数で返すためのFLandscapeFileTypeInfo、Validate関数で使用するTArray<std::string>、そしてLandscape自体の縦横の大きさ、海抜0を示す数値です。

今回はミニマムに進めるため、Landscapeの大きさを縦横256とします。

zeroHeightを定義しているのは、数値0が高さ0を表すわけではないからです。uint16でLandscapeの高さは表現され、(uint16)0は最低点、つまりマイナスの海抜を示します。そのため、uint16の中央値を海抜0として定義することで利便性向上を図っています。

参考:Unreal Engine でカスタム仕様の高さマップとレイヤーを作成する | Unreal Engine ドキュメント

 

続いて関数ですが、これら3つが、あのカスタムランドスケープインポータのドキュメントのページにある通りのオーバーライドする必要がある関数です。(4つ目のExport関数はエクスポートしないため実装しません)

ソースファイルは以下のように記述します。

初めにコンストラクタです。ここでGetInfo関数で返すFLandscapeFileTypeInfoを設定します。対応拡張子には”.txt”を追加します。また、エクスポートには対応しないため、”bSupportsExport”にfalseを設定します。

また、冒頭で挙げたテキストかどうかを判別するために、TArray<std::string>へ対応する文字列”Format1″, “Format2″を追加します。

 

2つ目はValidate関数です。ここでは、選択されたファイルがこのインポータに対応しているかをチェックします。

まずテキストファイルを読み込みます。ファイル入力ストリームを利用して、ファイルを開きます。ファイルが開けなければ、その旨を返します。

ファイルを開くことができたら、区切り文字まで文字列を読み込みます。

続いてテキストの確認です。読み込んだ文字列が、コンストラクタで追加した文字列のどれでもなければ、その旨を返します。

最後まで到達した場合は成功なので、今回サポートするLandscapeのサイズを返します。

 

3つ目はImport関数です。ここで正式にファイルを読み込み、Landscapeの高さデータを構築します。

まず、もう一度テキストを読み込みます。Validate関数を通しているため、ファイルを開いた際のエラーチェックは不要です。

次に、Landscapeの高さデータの配列の領域を確保します。TArray::AddUninitialized関数を使うことで、初期化を走らせることなく大量の領域を確保することができます。

最後に、Formatごとに高さデータを代入していきます。各Formatで、以下のルールで高さを決定しています。

  • Format1:中央からの距離を計算し、距離が遠いほど高さが最大に近付きます。
  • Format2:中央からの距離を計算し、距離が近いほど高さが最大に近付きます。

以上でカスタムランドスケープインポータを作成することができました。

 

5. カスタムランドスケープインポータをLandscapeEditorに登録する

仕上げに、作成したカスタムランドスケープインポータを登録します。登録は、プラグインのStartupModule関数で行います。

まず、ヘッダファイルに今回作成したカスタムランドスケープインポータを保持するTSharedPtrを宣言します。

次にソースファイルです。ヘッダファイルで宣言した変数に実体を代入します。

そして、LandscapeEditorModuleを取得します。ランドスケープインポータとして対応済みの拡張子リストを取得し、もし今回の拡張子”.txt”が対応していなければ今回のカスタムランドスケープインポータを対応拡張子として登録します。

以上でカスタムランドスケープインポータの作成が完了しました。実際に使ってみましょう。


 

UE5では”Shift+2″もしくは左上のDropdownメニューからLandscapeEditorを開くことができます。

続いて、”Manage”→”New”→”Import from File”と選択し、ランドスケープインポータ画面を表示します。

Heightmap Fileのファイル選択ダイアログを表示し、対応拡張子に先ほど記述した拡張子とその説明が表示されれば成功です。

冒頭に挙げたFormat1.txtとFormat2.txtを読み込ませれば、以下のようなLandscapeを得られると思います。

 

以上で動作確認も完了しました。おめでとうございます!これであなたも好きなファイルからLandscapeを生成することが可能になりました!!

お気付きの方もいるかと思いますが、今回読み取ったテキストファイルの代わりに画像ファイルなどの2次元データを対応拡張子とし、そのファイルの各要素をそのまま高さデータへ入れることで16bitPNGのように直感的なHeightmapを利用できるようになります!!

PNG画像やRAWファイル以外の、高さデータをLandscapeに変換したい時はぜひ作ってみてください!!!