見出し画像

UE4でDevelopers内の素材を参照しているファイルをチェックする簡単なツールをPythonを使って作ってみる

デザイナーのマスダです。
UE4でPythonが使えるようなので、ちょっとしたリネームツールやファイルチェッカを作ってみようという記事になります。
作成したツールは、エラー処理などはほぼせず、自分やセクション内で簡単に使えるようなものが出来ればいいな、程度の話になります。プログラマではないので、そこそこ動いたらOKのノリでいきましょう。

今回作るツールとしては、以下の物になります。

ファイルタイプを調べてリネーム
Developersに参照リンクがあるファイルを調べてコレクションに追加

※Pythonの使い方は説明しない(出来ない)ので、各自で習得よろしくお願いします。

Pythonを使う準備

まずはUE4でPythonを使う準備をしましょう。
UE4の[Edit]→[Plugins]からプラグインのチェックを入れます。
使用する機能によって、チェックを入れるプラグインは違ってきます。

準備がおわりましたらPythonが使えるかテストしてみましょう。 Output Logウィンドの左下の[Cmd]を[Python]に変更し、Print(”test”)と記述してエンターで実行してtestと表示されればOKかと思います。

これでPythonが使えるようになりました。

リネームツールを作る

手始めに、下図の表のようにUE4のファイルの種類でファイル名に自動でプレフィックスが付くリネームツールを作ってみましょう。

作業させたいパス下にある各ファイルに、上記指定のプレフィックスがファイル先頭に付くようにします。

import unreal

#ファイル取得やリネームに使う機能
assetLibrary = unreal.EditorAssetLibrary
utilityLibrary = unreal.EditorUtilityLibrary

def rename():
  #作業させたいパス
  workingPath = "/Game/Test"

  #指定したパス以下からアセットのパスを取得
  assetList = assetLibrary.list_assets(workingPath, True, False)

  #アセットのリストからアセットを取得
  for assetPath in assetList:
    assetData = assetLibrary.find_asset_data(assetPath)
    asset = assetData.get_asset()

    #アセットから名前・ファイルタイプを取得
    name = asset.get_name()
    asset_type = type(asset)

    typePrefix = ""

    #ファイルタイプで付けるプレフックスを選択
    if asset_type == unreal.StaticMesh:
        typePrefix = "SM"
    if asset_type == unreal.SkeletalMesh:
        typePrefix = "SK"
    if asset_type == unreal.Material:
        typePrefix = "M"
    if asset_type == unreal.MaterialInstanceConstant:
        typePrefix = "MI"
    if asset_type == unreal.MaterialFunction:
        typePrefix = "MF"
    if asset_type == unreal.ParticleSystem:
        typePrefix = "PS"
    if asset_type == unreal.Texture2D:
        typePrefix = "T"
    if asset_type == unreal.Blueprint:
        typePrefix = "BP"
    if typePrefix == "":
        continue

    #リネーム
    utilityLibrary.rename_asset(asset,"{}_{}".format(typePrefix, name))

if __name__ == "__main__":
    rename()

スクリプトが出来たら AssetRename.py など名前を付けてセーブして実行してみましょう。
UE4の[File]→[Python]→[Execute Python Script]から、作成したスクリプトを選択し実行します。

元のファイル名
実行後のファイル名

スクリプトが上手く動いていれば、/Game/Testフォルダ下にあるファイルにプレフィックスが追加されていると思います。ここでは実験的に少ないファイルで実行しているので手でリネームした方が早いと思われますが、多数ファイルを修正をする事になると、スクリプトなどで処理した方がミスも少なく時間もかかりません。

チェックツールを作る

次に、本題のDevelopers内にあるファイルを、Developers以外の箇所から参照しているファイルをチェックするツールを作ります。
Developersはテスト素材を置いておくのは便利ですが、パッケージ作成時に切り離されて素材のリンクが切れてしまったりすることがありました。そのようなファイルを修正できるように、Developers内にあるファイルをDevelopers以外の箇所から参照しているファイルをピックアップしてCollectionsに入れるようにします。

import unreal

#ファイル取得やチェックに使う機能
assetLibrary = unreal.EditorAssetLibrary
assetTagsSubsystem = unreal.AssetTagsSubsystem.get_default_object()
assetRegistryHelpers = unreal.AssetRegistryHelpers

def main():
  #チェックするパス
  workingPath = "/Game/Developers/"

  #コレクションに作成するフォルダ名
  collectionNames = \
  [
    "DevRef",\
    "DevRef_World",\
    "DevRef_Material",\
    "DevRef_MaterialInstanceConstant",\
    "DevRef_MaterialFunction",\
    "DevRef_WidgetBlueprint",\
    "DevRef_ParticleSystem",\
    "DevRef_StaticMesh",\
    "DevRef_AnimMontage",\
    "DevRef_Texture2D",\
    "DevRef_AnimSequence"
  ]

  makeCollection(collectionNames)
  devReferenceChack(workingPath, collectionNames)

def devReferenceChack(path, collectionNames):
  #path以下のアッセトを取得
  assets = assetLibrary.list_assets(path, True, False)

  #レジストリの取得
  assetReg = assetRegistryHelpers.get_asset_registry()

  for asset in assets:
    #参照しているファイルを取得
    refFiles = assetLibrary.find_package_referencers_for_asset(asset, False)

    #refFileのパスに”Developers"が含まれてない場合外部から参照されているとみなす。
    for refFile in refFiles:
      regAsset = assetReg.get_assets_by_package_name(refFile)

      if (len(regAsset) > 0):
        assetData = regAsset[0]
        refAssetPath = str(assetData.object_path)

        #参照ファイルのパスに"Developers"がなければコレクションに追加
        if not("Developers" in refAssetPath):
          assetType = assetData.get_editor_property("asset_class")
          assetCollectionName = "DevRef_" + str(assetType)
          assetCollections = assetTagsSubsystem.get_collections_containing_asset_data(assetData)

          #コレクションの名前があればそのコレクションに、なければDevRefへ追加
          #既にコレクションにある物はスルー
          if not(assetCollectionName in collectionNames):
            if not("DevRef" in assetCollections):
              assetTagsSubsystem.add_asset_data_to_collection("DevRef", assetData)
          elif not(assetCollectionName in assetCollections):
            assetTagsSubsystem.add_asset_data_to_collection(assetCollectionName, assetData)

  print("CheckEND!!!!")

#コレクションフォルダを作成する。
def makeCollection(collectionNames):
  shareType = unreal.CollectionShareType.LOCAL

  for collectionName in collectionNames:
    #既存のコレクションがあれば削除
    if assetTagsSubsystem.collection_exists(collectionName):
      assetTagsSubsystem.destroy_collection(collectionName)

    #コレクション作成
    if not(assetTagsSubsystem.collection_exists(collectionName)):
      assetTagsSubsystem.create_collection(collectionName, shareType)

if __name__ == "__main__":
    main()

今回はConTent下図のように、Testフォルダ内のParticleSystemからDevelopersのTestMeshを参照しているファイルを作りテストしてみました。

Developersフォルダ以外からの参照

スクリプトが出来たら、 DevRefCheck.py など名前を付けてセーブして実行してみましょう。
UE4の[File]→[Python]→[Execute Python Script]から、作成したスクリプトを選択し実行します。

スクリプト実行後のコレクション

Developersフォルダ内にあるファイルを、Developers以外の箇所から参照しているファイル(PS_ParticleSystem)が、CollectionsのDevRef_ParticleSystemの項目に入っていると思います。
Collectionsにピックアップされたファイルのリンクを確認してみましょう。

参照ビューワ(PS_ParticleSystem)

ファイルのリンクを修正を行い、Developersのファイルを使用しないようにします。ここではテスト用の一つのファイルですが、多数ファイルのリンクを一つ一つ追うのは結構大変です。スクリプトでツールを作ることで楽にチェックできるようになりました。

終わりに

スクリプトは便利ですが、何でもかんでも解決できるわけでもないので、費用対効果を考えて実現できる範囲で便利に使っていきたいですね。
突っ込みどころも多いスクリプトかと思いますが、動けばOKのノリですのでご容赦ください。

UE5でもPythonは使用できてエディタ機能とかと合わせて色々とできるようなので、続けて勉強していければと思います。ではまた。