はじめに
購入したサウンドアセットを確認するためだけのプロジェクトがあり、それがまぁまぁの容量を取っているので「アセットをどこかにエクスポートしてwav形式にすれば容量削減できるんじゃないか」と考え、せっかくなのでPythonを使って実装にチャレンジしてみました。
結論として、uasset形式からwav形式に変換したあとの容量の差は600MB減少した程度で効果はさほどありませんでした。
この愚かなチャレンジの結果はさておいて、UE4でのPythonの利用やエクスポートの仕組み、Editor Utility Widget(以下EUWという)との連携は誰かの役に立つと思うので、紹介をしてみた次第です。
ここで紹介する内容ははUE4.27.2で実装したものです。それ以外のバージョンでは確認していません。ご了承ください。
ソースコード
ソースコードは全部で60行程度なので、直接ここに貼るだけに留めます。
今回の一括エクスポートについては、9割9分をPythonで実装しました。ほぼすべての行にコメントを書いてしまったので、特にプログラムの解説はしません。
import unreal # 出力タスク配列. export_tasks = [] # 現在選択中のオブジェクト.(ContentBrowser内) selected_objs = unreal.EditorUtilityLibrary.get_selected_assets() # 選択中のオブジェクトから処理対象となるアセットクラスのみを取り出す.(SoundWaveアセットのみを対象とする) # 右辺の書き方を「リスト内包表記」という.(https://docs.python.org/ja/3.7/tutorial/datastructures.html#list-comprehensions) process_target_objs = [obj for obj in selected_objs if obj.get_class() == unreal.SoundWave.static_class()] # タスクの最大進捗数. total_frames = len(process_target_objs) # タスク進捗ダイアログに表示されるテキスト. text_label = "Working!" # タスクの進捗率を監視する. with unreal.ScopedSlowTask(total_frames, text_label) as slow_task: # タスクの進捗についてのダイアログを作成(未作成の場合) slow_task.make_dialog(True) for obj in process_target_objs: # ユーザーがダイアログの「Cancel」ボタンを押した. if slow_task.should_cancel(): break # 進捗を1つ進める. slow_task.enter_progress_frame(1) # 選択したアセットのパスを取得(先頭の[/Game/]部分は削除). path = obj.get_path_name().replace('/Game/', '') # 上で取得された文字列の「アセット名.アセット名」部分が末尾から何文字目になるか計算する. name_len = len(obj.get_name())*2+1 # +1はドット部分. # 出力するためのオブジェクトを生成. task = unreal.AssetExportTask() # 出力に必要な情報を設定する. # 出力対象のオブジェクト. task.set_editor_property("object", obj) # 出力先と出力ファイル名+拡張子. # 出力先はデスクトップで固定.「あなたのユーザー名」は自身のユーザーアカウント名に読み直してください. task.set_editor_property("filename", "C:/Users/あなたのユーザー名/Desktop/UE_Sound_Exported/{}.wav".format(path[:-name_len]+obj.get_name())) # 使用するエクスポーター.自動で決定されるらしいが、念の為. # 今回はSoundWaveアセットをWAVファイルに変換して出力したいのでSoundExporterWAVを指定. task.set_editor_property("exporter", unreal.SoundExporterWAV()) # 常に上書きして出力する. task.set_editor_property("replace_identical", True) # タスクを積む export_tasks.append(task) # 逐次タスクを実行する事もできる. #unreal.Exporter.run_asset_export_task(task) # 積んだタスクを実行 unreal.Exporter.run_asset_export_tasks(export_tasks) # 実行が完了したことを知らせるダイアログの作成. unreal.EditorDialog.show_message("Sound Asset Exporter", "Task Completed", unreal.AppMsgType.OK)
使い方
1. プロジェクトのContentフォルダ内にPythonフォルダを作る
ContentBrowser内でContentフォルダ内に新しく「Python」という名前のフォルダを作成します。UE4はデフォルトでいくつかのパスにあるPythonファイルを認識し、エディタ側から呼び出せるようにうまいことやってくれます。Unreal Editor の Python パス
2. Pythonフォルダ内でpythonファイルを新規作成し、ソースコードをコピペ
pythonファイルはContentBrowserで作成することができないので、エクスプローラー上で作ります。 まず「右クリック -> 新規作成 -> テキストファイル」でテキストファイルを作成し「[いい感じのファイル名].py」にします。pythonファイルが無事に作成できたらページ上部のソースコードをコピペします。
3. EUWを作る
pythonファイルはUE4のコマンドラインから呼び出すこともできますが、せっかくなのでEUWから呼び出せるようにします。 通常のEUWを作る手順とどうようにEUWアセットを作成し、ボタンとテキストを追加します。
Event GraphはボタンウィジェットのOnClickedイベントを追加し、ExecutePythonCommandノードを接続します。ExecutePythonCommandノードのパラメータには2番で作成したファイル名を拡張子付きで指定します。
4. 実行して結果を確認する
3番で作成したEUWアセットをContentBrowser上で右クリックし「Run Editor Utility Widget」ボタンを押してEUWを実行します。 ウィンドウが表示されたら、ContentBrowser上でエクスポートしたいSoundWaveアセットを選択し実行したEUWにあるボタンを押します。しばらくすると「Task Completed」と書かれたウィンドウが表示されますので、OKボタンを押して閉じ、デスクトップにエクスポートされているか確認します。 デスクトップには新しく「UE_Sound_Exportedフォルダ」が追加されているはずです。
ContentBrowser上でSoundWaveアセットを選択するときはContentBrowserのフィルタリング機能を使ってSoundWaveアセットのみを表示対象とすると便利です。(一応プログラムにはSoundWaveアセット以外のアセットはエクスポート対象から除外されるようにしています)
おわりに
当初の目論見は外れてしまいましたが、結構楽しく実装できました。通常、SoundWaveアセットをエクスポートすると直接デスクトップにwavファイルがエクスポートされてしまいますが、今回の拡張のおかげでContentBrowser上のディレクトリ構造を維持したままデスクトップにエクスポートすることができます。個人的にお気に入りポイントです。
参考資料
Pythonを使ってエディタ拡張する際の始まりの地。まずはここをザッと読むことをおすすめ。
Python を使用したエディタのスクリプティング | Unreal Engine ドキュメント
UE4で呼び出せるPython(Unreal Python)のドキュメント
Unreal Python API Documentation — Unreal Python 4.27 (Experimental) documentation
EUWとPythonを使ってリネームツールを作成するチュートリアル。日本語。これも見て。
UE4 | PythonとEditor Utility Widgetでアセットリネームツールを作ろう! - YouTube