こんにちは、株式会社Leon Gameworksの遠藤です。
今回は、アセットのインポート時に任意の設定を自動適用するEditor Utility Blueprint(EUB)を作成します。テクスチャのインポート時にsRGBの設定を自動的に変更する処理を例に、実装方法を解説します。
0:動作環境
本記事はUE5.8.3を基に執筆しており、画面のスクリーンショットはエディタの言語設定を「英語」として撮影しています。
なお、本記事で作成するプロジェクト一式は、以下よりダウンロード可能です。
1:インポート時のイベントを受け取る
まずは、EditorUtilityObjectを親クラスとするEditor Utility Blueprint(EUB)を作成します。
作成したEUBを開き、[Run]イベントをオーバーライドします。続いて、[Import Subsystem]の[OnAssetPostImport]イベントにカスタムイベントをバインドします。これにより、アセットのインポート完了時に処理を実行できるようになります。
2:設定の自動適用
OnAssetPostImportイベントの引数[In Created Object]には、インポートによって生成されたアセットが渡されます。今回はテクスチャを対象とするため、Texture2Dにキャストします。
続いて、[Set Editor Property]ノードを使用して、アセットのプロパティを変更します。今回は、テクスチャの[sRGB]を[false]に設定します。
これで、インポート時に設定を自動適用する処理が完成しました。最後に、[Class Defaults]の[Run on Start-up]にチェックを入れます。これにより、エディタ起動時にEUBが自動実行されるようになります。ツールの挙動を確認するには、一度エディタを再起動しましょう。
3:Unreal Python
ここまではEUBを使った実装方法を紹介しましたが、同様の処理はUnreal Pythonでも実現できます。ここでは、インポートしたテクスチャの名前や保存先に応じて設定を自動変更するPythonスクリプトを紹介します。
"""インポート通知に応じて、Texture2Dへ制作ルールを適用する。"""
import traceback
import unreal
ROOT_PATH = "/Game/EUTools24/Textures/"
UI_PATH = ROOT_PATH + "UI/"
# importlib.reload()でも、登録済みの関数への参照を保持する。
if "_STATE" not in globals():
_STATE = {"subsystem": None, "callback": None}
def apply_texture_rules(texture):
"""対象に設定を適用する。変更した場合はTrueを返す。"""
if not isinstance(texture, unreal.Texture2D):
return False
asset_path = texture.get_path_name()
if not asset_path.startswith(ROOT_PATH):
return False
settings = []
# ルール1:末尾が_ORMなら、マスク用の設定を適用する。
if texture.get_name().upper().endswith("_ORM"):
settings.extend([
("compression_settings", unreal.TextureCompressionSettings.TC_MASKS),
("srgb", False),
])
# ルール2:UIフォルダ内なら、Texture GroupをUIにする。
# elifにはせず、両方に一致した場合は両方の設定を適用する。
if asset_path.startswith(UI_PATH):
settings.append(("lod_group", unreal.TextureGroup.TEXTUREGROUP_UI))
if not settings:
return False
changed = []
for property_name, target_value in settings:
# 圧縮設定の変更後に、sRGBの現在値を取得する順序になる。
current_value = texture.get_editor_property(property_name)
if current_value != target_value:
texture.set_editor_property(property_name, target_value)
changed.append(property_name)
if changed:
unreal.log(f"[AutoTexture] {asset_path}: Updated {', '.join(changed)}")
else:
unreal.log(f"[AutoTexture] {asset_path}: No change required")
# 保存は、インポート処理の完了後に通常の保存操作で行う。
return bool(changed)
def _on_asset_post_import(factory, created_object):
"""ImportSubsystemから呼ばれる、2引数のコールバック。"""
try:
# NoneやTexture2D以外も、apply_texture_rules内で対象外になる。
apply_texture_rules(created_object)
except Exception:
unreal.log_error("[AutoTexture] Failed to apply settings:\n"
+ traceback.format_exc())
def stop():
"""このモジュールが登録したコールバックだけを解除する。"""
subsystem = _STATE["subsystem"]
callback = _STATE["callback"]
if subsystem is not None and callback is not None:
subsystem.on_asset_post_import.remove_callable(callback)
unreal.log("[AutoTexture] Stopped")
_STATE["subsystem"] = None
_STATE["callback"] = None
def start():
"""監視を開始する。登録済みであれば、旧コールバックを解除する。"""
stop()
subsystem = unreal.get_editor_subsystem(unreal.ImportSubsystem)
if subsystem is None:
raise RuntimeError("ImportSubsystemを取得できません。")
callback = _on_asset_post_import
subsystem.on_asset_post_import.add_callable_unique(callback)
_STATE["subsystem"] = subsystem
_STATE["callback"] = callback
unreal.log(f"[AutoTexture] Started: {ROOT_PATH}")
4:まとめ
今回は、アセットのインポート時に設定を自動適用する方法を紹介しました。シンプルな処理ですが、インポート後に毎回行う設定変更を自動化できるため、様々な場面で活用できます。
今回はテクスチャを例にしましたが、メッシュやサウンドなど、ほかの種類のアセットにも応用可能です。制作環境に合わせて、ぜひ活用してみてください。
本記事で作成したプロジェクト一式へのリンクはこちらです。
株式会社Leon Gameworks
●公式サイト
www.leon-game.co.jp
●X(Twitter)
@Leon_Gameworks
トンコツ(遠藤俊太)
●トンコツ開発ブログ
shuntaendo.hatenablog.com
●X(Twitter)
@tonkotsu3656
TEXT_トンコツ(Leon Gameworks)
EDIT_小村仁美 / Hitomi Komura(CGWORLD)、オムライス駆