ブループリントおよび Python でレベルオブディテールを作成する

Unreal Editor で、ブループリントおよび Python を使用してレベルオブディテール (LOD) を自動設定する方法を説明します。

Windows
MacOS
Linux

メッシュのレベルオブディテール (LOD) を作成することは、ビジュアル クオリティを低下させることなくゲームのパフォーマンスおよびフレームレートを向上させるうえで有効な方法です。

一般的には、メッシュに含まれる三角ポリゴンの数が多いほどこれらの画面での表示が小さくなり、GPU によるレンダリングが困難になります。 同時に多くの詳細なメッシュをレンダリングしようとすると、フレームレートが遅くなる場合があります。 ただし、シーンに含まれるすべてのメッシュを同じ忠実度でレンダリングする必要は通常はありません。 つまり、遠くにあるメッシュについては、ビジュアル クオリティーの面で違いを際立たせることなく、三角ポリゴンが少ない、細部を省略したバージョンのメッシュに入れ替えることができます。

Unreal Engine 4 には、各フレームでメッシュが占めている画面の範囲に基づいて、ランタイム時での表示に最も適したバージョンのメッシュを自動的に選択する、ビルトインの LOD 管理システムが搭載されています。 このシステムでは、メッシュの異なる代替バージョンを事前にエディタで設定しておく必要があります。

エディタでは、指定した各しきい値に対してメッシュを段階的に単純化することで、スタティック メッシュ アセットのレベルオブディテールを自動的に生成することができます。 このシステムの仕組みや、スタティック メッシュ エディタで自動生成を設定する方法については、「自動 LOD 生成」を参照してください。

ただし、エディタでこれらのレベルオブディテールを自動生成できても、プロジェクトに含まれるスタティック メッシュ アセットを 1 つずつ開いて設定を行うことは困難な場合があります。 アセットをまとめて編集することは可能ですが、異なるスタティック メッシュ アセットにそれらの性質に基づいて異なる設定を適用する場合は有効ではありません。例えば、メッシュ内にある既存の三角ポリゴン数や、アセットの命名規則に基づいて異なる削減設定を適用する場合などがこれにあたります。 また、スクリプティングした、より大きなカスタム アセット パイプライン内のサブステップとして LOD を作成する場合も、この方法は有効ではありません。 このような場合は、ブループリントまたは Python を使用して、自動 LOD 作成システムをスクリプティングすることができます。

前提条件: 今回の使用が初めての場合は、 Editor Scripting Utilities プラグイン をインストールしてください。 詳細については、「エディタのスクリプティングと自動化」 を参照してください。

新規レベルオブディテールを作成する

実装方法を選んでください。

ブループリント

Python

LOD の管理が必要なノードは、[Editor Scripting] > [Static Mesh] カテゴリに表示されます。

これらのノードを使用するには、 PlacedEditorUtilityBase クラスなど、エディタのみのクラスから派生したブループリント クラスである必要があります。 詳細については、「ブループリントを使用したエディタのスクリプティング」を参照してください。

  • 重要になるのは、渡したスタティック メッシュ アセットのレベルオブディテールを自動的に作成する Set Lods ノードです。これを使用するには、このノードと共に、画面サイズのしきい値、および作成する各レベルオブディテールの相対的な三角ポリゴン割合を定義する一連の削減設定を提供する必要があります。 以下の例を見てみましょう。

    EditorScriptingMeshReductionOptions ノードの Reduction Settings 入力に渡す最初の EditorScriptingMeshReductionSettings 項目は無効です。 LOD 0 には常にメッシュのすべての三角ポリゴンが含まれます。

  • スタティック メッシュに対して現在設定されているレベルオブディテールに関する情報を取得するには、Get Lod Count および Get Lod Screen Sizes を使用できます。

  • また、既存の LOD をすべて削除するには Remove Lods を使用できます (メッシュのすべての三角ポリゴンが含まれる LOD = 0 以外の場合)。

  • LOD を設定することで、スタティック メッシュ アセットに変更が加えられます。 加える変更を維持する場合は、後から Save Asset または Save Loaded Asset などのノードも使用する必要があります。

以下の例では、各スタティック メッシュ アセットを入力パス内に順番にロードします。 最小しきい値より多くの頂点が含まれるスタティック メッシュについては、追加の LOD が 3 つ設定されて、後に保存されます。

LOD 管理関数は unreal.EditorStaticMeshLibrary クラスにあります。

  • 重要になるのは、渡したスタティック メッシュ アセットのレベルオブディテールを自動的に作成する unreal.EditorStaticMeshLibrary.set_lods() 関数です。この関数を使用するには、画面サイズのしきい値、および作成する各レベルオブディテールの相対的な三角ポリゴン割合を定義する一連の EditorScriptingMeshReductionSettings を含む EditorScriptingMeshReductionOptions オブジェクトを渡す必要があります。 以下の例を見てみましょう。

    EditorScriptingMeshReductionOptions.reduction_settings 配列で設定した最初の EditorScriptingMeshReductionSettings アイテムには影響はありません。LOD 0 には常にメッシュのすべての三角ポリゴンが含まれます。

  • スタティック メッシュに対して現在設定されているレベルオブディテールに関する情報を取得するには、unreal.EditorStaticMeshLibrary.get_lod_count() および unreal.EditorStaticMeshLibrary.get_lod_screen_sizes を使用できます。

  • また、既存の LOD をすべて削除するには unreal.EditorStaticMeshLibrary.remove_lods() を使用できます (メッシュにすべての三角ポリゴンが含まれる LOD = 0 以外の場合)。

  • LOD を設定することで、スタティック メッシュ アセットに変更が加えられます。 加える変更を維持する場合は、後から unreal.EditorAssetLibrary.save_asset() または unreal.EditorAssetLibrary.save_loaded_asset() などの関数も使用する必要があります。

以下の例では、各スタティック メッシュ アセットを入力パス内に順番にロードします。 最小しきい値より多くの頂点が含まれるスタティック メッシュについては、追加の LOD が 3 つ設定されて、後に保存されます。

import unreal
asset_path = "/Game/studio"
# 特定のスタティック メッシュ アセットに対する新しい LOD を生成する関数を定義します。
def apply_lods(static_mesh):
    # メッシュが十分に複雑かどうかを確認します。
    number_of_vertices = unreal.EditorStaticMeshLibrary.get_number_verts(static_mesh, 0)
    if number_of_vertices < 10:
        return
    print("treating asset: " + static_mesh.get_name())
    print("existing LOD count: " + str(unreal.EditorStaticMeshLibrary.get_lod_count(static_mesh)))
    # レベルオブディテールの自動生成のためのオプションを設定します。
    options = unreal.EditorScriptingMeshReductionOptions()
    # 3 つの新しいレベルオブディテールをリクエストします。 各レベルオブディテールには次が含まれます:
    # - 完全に細部が表示されるメッシュの三角ポリゴン数に対して、このレベルで維持される三角ポリゴンの割合
    # - このレベルオブディテールが表示される画面スペースのしきい値。
    options.reduction_settings = [ unreal.EditorScriptingMeshReductionSettings(1.0, 1.0),
        unreal.EditorScriptingMeshReductionSettings(0.8, 0.75),
        unreal.EditorScriptingMeshReductionSettings(0.6, 0.5),
        unreal.EditorScriptingMeshReductionSettings(0.4, 0.25)
    ]
    # 自動計算するのではなく、上で設定された画面スペースのしきい値を使用します。
    options.auto_compute_lod_screen_size = False
    # スタティック メッシュ アセットのオプションを設定します。
    unreal.EditorStaticMeshLibrary.set_lods(static_mesh, options)
    # 変更を保存します。
    unreal.EditorAssetLibrary.save_loaded_asset(static_mesh)
    print("new LOD count: " + str(unreal.EditorStaticMeshLibrary.get_lod_count(static_mesh)))
# パス内にあるすべてのアセットのリストを取得します。
all_assets = unreal.EditorAssetLibrary.list_assets(asset_path)
# アセットをすべてメモリにロードします。
all_assets_loaded = [unreal.EditorAssetLibrary.load_asset(a) for a in all_assets]
# スタティック メッシュのみを含めるよう、リストをフィルタリングします。
static_mesh_assets = unreal.EditorFilterLibrary.by_class(all_assets_loaded, unreal.StaticMesh)
# リスト内の各スタティック メッシュで上記の関数を実行します。
map(apply_lods, static_mesh_assets)

別なアプローチとして、各スタティック メッシュ アセットに対して LOD Group オプションを設定する方法があります。 このオプションでは、LevelArchitectureSmallPropLargeProp、または HighDetail など、プロジェクトの「BaseEngine.ini」ファイル内の [StaticMeshLODSettings] セクションで定義されている、事前設定済みの LOD 削減設定の 1 つをメッシュに使用させることができます。

例:

import unreal
asset_path = "/Game/studio/"
def set_high_detail(static_mesh):
    # LOD グループを設定します。
    static_mesh.set_editor_property("lod_group", "HighDetail")
    # アセットを保存します。
    unreal.EditorAssetLibrary.save_loaded_asset(static_mesh)
# パス内にあるすべてのアセットのリストを取得します。
all_assets = unreal.EditorAssetLibrary.list_assets(asset_path)
# アセットをすべてメモリにロードします。
all_assets_loaded = [unreal.EditorAssetLibrary.load_asset(a) for a in all_assets]
# スタティック メッシュのみを含めるよう、リストをフィルタリングします。
static_mesh_assets = unreal.EditorFilterLibrary.by_class(all_assets_loaded, unreal.StaticMesh)
# リスト内の各スタティック メッシュで上記の関数を実行します。
map(set_high_detail, static_mesh_assets)

このシステムの仕組みやエディタで使用する方法については、「自動 LOD 生成」を参照してください。

LOD を別のスタティック メッシュから再利用する

前に概要を説明したプロセスで、スタティック メッシュの LOD を自動的に生成する別の方法として、スタティック メッシュ (ソース スタティック メッシュ) にすでにある LOD を利用して、別のスタティック メッシュ ( 宛先 スタティック メッシュ) の LOD として再利用します。

実装方法を選んでください。

ブループリント

Python

ブループリント スクリプトで既存の LOD を再利用するには、[Editor Scripting] > [Static Mesh] > [Set Lod From Static Mesh] ノードを使用します。 

スタティック メッシュから LOD を設定する

このノードでは次の入力が必要です。

  • 宛先スタティック メッシュへの参照。 新しい LOD を作成するスタティック メッシュです。 まずこのアセットを [Editor Scripting] > [Asset] > [Load Asset] ノードを使用してロードする必要があります。

  • 宛先スタティック メッシュで作成する LOD のインデックス。

    宛先スタティック メッシュに同じインデックスの LOD がある場合は、上書きされます。

  • ソース スタティック メッシュへの参照。 宛先スタティック メッシュに渡す、既存の LOD を保持するスタティック メッシュです。 前と同様に、まずこのアセットを [Editor Scripting] > [Asset] > [Load Asset] ノードを使用してロードする必要があります。

  • 宛先スタティック メッシュで使用する、ソース スタティック メッシュの LOD のインデックスです。

  • ソース LOD のマテリアル スロットと宛先スタティック メッシュに存在するスロットをマージするかどうかを決定する Boolean パラメータです。 この設定を有効にすると、関数は宛先メッシュのセクションと同じマテリアルを割り当てたソース ジオメトリのセクションを検索します。 対象が見つかると、LOD のセクションを再マッピングして、宛先スタティック メッシュにある既存のセクションとの一致を試みます。 両方のスタティック メッシュが同じマテリアルを使用している場合、これによりメモリをいくらか節約できることがあります。この設定を無効のままにすると、ソース LOD のすべてのメッシュ セクションが宛先スタティック メッシュに追加されます。

LOD の設定は宛先スタティック メッシュ アセットに変更を加えます。 加える変更を維持する場合は、後から Save Asset または Save Loaded Asset などのノードも使用する必要があります。

例えば、次のスクリプトはソース スタティック メッシュから指定 LOD を取得し、指定された異なる LOD インデックスで宛先スタティック メッシュでジオメトリを再利用します。

Set Lod from Static Mesh ノードを実行すると、ソース スタティック メッシュの LOD のコピーを宛先スタティック メッシュに追加します。 スタティック メッシュ アセット間に継続的な接続はありません。したがってこの時点以降のスタティック メッシュへの変更は宛先スタティック メッシュに自動的に反映されません。

Python スクリプトで LOD を再利用するには、unreal.EditorStaticMeshLibrary.set_lod_from_static_mesh() 関数を呼び出します。 次の項目をこの関数に渡す必要があります。

  • 宛先スタティック メッシュ。 新しい LOD を作成するスタティック メッシュです。 まずこのアセットを unreal.EditorAssetLibrary.load_asset() 関数を使用してロードする必要があります。

  • 宛先スタティック メッシュで作成する LOD のインデックス。 これには 0 より大きい値が必要です。宛先スタティック メッシュの LOD 0 を置き換えることはできません。

    宛先スタティック メッシュに同じインデックスの LOD がある場合は、上書きされます。

  • ソース スタティック メッシュ。 宛先スタティック メッシュに渡す、既存の LOD を保持するスタティック メッシュです。 前と同様に、まずこのアセットを unreal.EditorAssetLibrary.load_asset() 関数を使用してロードする必要があります。

  • 宛先スタティック メッシュで使用する、ソース スタティック メッシュの LOD のインデックスです。

  • 宛先スタティック メッシュのマテリアル スロットをマージするかどうかを決定する Boolean パラメータです。 このパラメータを True に設定すると、この関数は宛先メッシュのセクションと同じマテリアルを割り当てたソース ジオメトリのセクションを検索します。 対象が見つかると、LOD のセクションを再マッピングして、宛先スタティック メッシュにある既存のセクションとの一致を試みます。 このパラメータを False に設定すると、ソース LOD のすべてのメッシュ セクションは宛先スタティック メッシュに追加されます。

この LOD を設定することで、スタティック メッシュ アセットに変更が加えられます。 加える変更を維持する場合は、後から unreal.EditorAssetLibrary.save_asset() または unreal.EditorAssetLibrary.save_loaded_asset() などの関数も使用する必要があります。

例えば、次のスクリプトは指定したソース スタティック メッシュの LOD 0 を取得し、複雑な宛先スタティック メッシュの LOD 1 としてジオメトリを再利用します。

import unreal
destination_name = "/Game/MyGeometries/Accumulator_case"
source_name = "/Game/MyGeometries/Simplified_box"
def set_mesh_as_lod(destination_name, source_name):
    destination_mesh = unreal.EditorAssetLibrary.load_asset(destination_name)
    source_mesh = unreal.EditorAssetLibrary.load_asset(source_name)
    lod_count = unreal.EditorStaticMeshLibrary.get_lod_count(destination_mesh)
    print("Current LOD count: " + str(lod_count))
    slot_replaced = unreal.EditorStaticMeshLibrary.set_lod_from_static_mesh(destination_mesh, 1, source_mesh, 0, True)
    if slot_replaced > 0:
        print("Added mesh as LOD for slot " + str(slot_replaced))
        lod_count = unreal.EditorStaticMeshLibrary.get_lod_count(destination_mesh)
        print("New LOD count: " + str(lod_count))
        unreal.EditorAssetLibrary.save_loaded_asset(destination_mesh)
    else
        unreal.log_error("Unable to add mesh as LOD!")
set_mesh_as_lod(destination_name, source_name)

unreal.EditorStaticMeshLibrary.set_lod_from_static_mesh() 関数を実行すると、ソース スタティック メッシュの LOD のコピーを宛先スタティック メッシュに追加します。 スタティック メッシュ アセット間に継続的な接続はありません。したがってこの時点以降のスタティック メッシュへの変更は宛先スタティック メッシュに自動的に反映されません。

新しい Unreal Engine 4 ドキュメントサイトへようこそ!

あなたの声を私たちに伝えるフィードバックシステムを含め、様々な新機能について開発をおこなっています。まだ広く使える状態にはなっていないので、準備ができるまでは、ドキュメントフィードバックフォーラムで、このページについて、もしくは遭遇した問題について教えていただけると助かります。

新しいシステムが稼働した際にお知らせします。

フィードバックを送信