Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Python / BlueprintによるUnreal Engineの自動化 / GTMF2019

506 views

Published on

Unreal EngineにはPythonやBlueprintを使って手軽に自動化・効率化できる機能があります。
UE4.22で追加されたEditor Utility WidgetやDatasmithのカスタムインポートなど、自動化・効率化に関する機能の紹介と、Python / Blueprintによる実装例などをご紹介したいと思います。

Published in: Technology
  • DOWNLOAD FULL BOOKS, INTO AVAILABLE FORMAT ......................................................................................................................... ......................................................................................................................... 1.DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... 1.DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... 1.DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... 1.DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... 1.DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... 1.DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • DOWNLOAD FULL BOOKS, INTO AVAILABLE FORMAT ......................................................................................................................... ......................................................................................................................... ,DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... ,DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... ,DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... ,DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... ,DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... ,DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/yyxo9sk7 } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Python / BlueprintによるUnreal Engineの自動化 / GTMF2019

  1. 1. Python / Blueprintによる Unreal Engineの自動化 Epic Games Japan / Technical Artist 小林浩之
  2. 2. #UE4 | @UNREALENGINE 自己紹介 小林 浩之 Epic Games Japan / Technical Artist スクウェア・エニックス大阪で背景TAを2年ほど 今年2月からEGJのエンタープライズ分野のサポートとして入社
  3. 3. #UE4 | @UNREALENGINE 目次 • 大規模開発における作業効率化・自動化の需要 • Unreal Engine 4の作業効率化・自動化ツール紹介 • 実装例 • Datasmithインポートの効率化 Blueprint • 命名規則に応じたアセットリネーム Editor Utility Widget & Blueprint • Pythonによるインスタンシング Python • インスタンスを個別のStatic Meshに変換 Python
  4. 4. #UE4 | @UNREALENGINE 目次 • 大規模開発における作業効率化・自動化の需要 • Unreal Engine 4の作業効率化・自動化ツール紹介 • 実装例 • Datasmithインポートの効率化 Blueprint • 命名規則に応じたアセットリネーム Editor Utility Widget & Blueprint • Pythonによるインスタンシング Python • インスタンスを個別のStatic Meshに変換 Python
  5. 5. #UE4 | @UNREALENGINE 大規模開発における作業効率化・自動化の需要 大量に配置されたオブジェクトの整理、膨大なアセットの管理など、 手作業でやっているとコストがかかるりすぎる・・・ 時間が足りない・・・ クオリティアップにコストを割けない・・・
  6. 6. #UE4 | @UNREALENGINE 大規模開発における作業効率化・自動化の需要 オブジェクト整理作業 アセット管理作業 などなど 自動化
  7. 7. #UE4 | @UNREALENGINE McLarenによる事例 Unreal Engineへの CADデータインポートの自動化
  8. 8. #UE4 | @UNREALENGINE McLarenによる事例 インポートフローの改善
  9. 9. #UE4 | @UNREALENGINE 目次 • 大規模開発における作業効率化・自動化の需要 • Unreal Engine 4の作業効率化・自動化ツール紹介 • 実装例 • Datasmithインポートの効率化 Blueprint • 命名規則に応じたアセットリネーム Editor Utility Widget & Blueprint • Pythonによるインスタンシング Python • インスタンスを個別のStatic Meshに変換 Python
  10. 10. #UE4 | @UNREALENGINE Bluetility (Blueprint Utility) Blueprintを使ったスクリプティング
  11. 11. #UE4 | @UNREALENGINE Bluetility プラグイン > Editor Scripting Utilities
  12. 12. #UE4 | @UNREALENGINE Unreal Python Pythonによるエディタスクリプティング
  13. 13. #UE4 | @UNREALENGINE Unreal Python プラグイン > Python Editor Script Pluginにチェックで有効化
  14. 14. #UE4 | @UNREALENGINE Unreal Python アウトプットログから直接入力 実行方法
  15. 15. #UE4 | @UNREALENGINE Unreal Python .pyファイルのパス指定で実行 実行方法
  16. 16. #UE4 | @UNREALENGINE Unreal Python エディタ起動時に実行
  17. 17. #UE4 | @UNREALENGINE Editor Utility Widget UMG&Blueprintでエディタ拡張
  18. 18. #UE4 | @UNREALENGINE Editor Utility Widget コンテンツブラウザで右クリック>Editor Utilities>Editor Widgetから作成
  19. 19. #UE4 | @UNREALENGINE Editor Utility Widget
  20. 20. #UE4 | @UNREALENGINE Editor Utility Widget UIに必要な機能(ボタンやテキストなど)をD&Dで置く
  21. 21. #UE4 | @UNREALENGINE Editor Utility Widget UIからの処理をBlueprintで作成
  22. 22. #UE4 | @UNREALENGINE Editor Utility Widget アセット右クリック>Run Editor Utility WidgetでWindow立ち上げ、実行
  23. 23. #UE4 | @UNREALENGINE Editor Utility Widget EGJ 岡田による解説記事 [UE4]エディタ上で動作するツール・エディタ拡張をUMGで簡単に作れる Editor Utility Widget について https://qiita.com/EGJ-Kaz_Okada/items/9f530db3b53d0fde3f20 [UE4]Editor Utility Widgetでツール・エディタ拡張を作る際のUndo/Redo の実装方法について https://qiita.com/EGJ-Kaz_Okada/items/985b98fb934d751f4f69
  24. 24. #UE4 | @UNREALENGINE 目次 • 大規模開発における作業効率化・自動化の需要 • Unreal Engine 4の作業効率化・自動化ツール紹介 • 実装例 • Datasmithインポートの効率化 Blueprint • 命名規則に応じたアセットリネーム Editor Utility Widget & Blueprint • Pythonによるインスタンシング Python • インスタンスを個別のStatic Meshに変換 Python
  25. 25. #UE4 | @UNREALENGINE 実装例:Datasmithインポートの効率化
  26. 26. #UE4 | @UNREALENGINE Datasmithとは CADソフトなどのデータをUE4用に変換してインポートする機能 (Unreal Studioのみ) Datasmith
  27. 27. #UE4 | @UNREALENGINE Datasmithによって大幅に効率化されるが・・・ CADデータの場合細かいネジなどのパーツまで含んだデータになっている場合が多い 環境によっては処理負荷が高くなってしまう可能性も
  28. 28. #UE4 | @UNREALENGINE Datasmithによって大幅に効率化されるが・・・ リアルタイムエンジンでスムーズに描画するためには ほとんど描画されないような小さいパーツは削除したり、一つにまとめる必要がある
  29. 29. #UE4 | @UNREALENGINE 普通にインポートして後から削除しようとするとする場合 パーツ数が膨大だと作業コストが高くなってしまう インポート 小さいパーツを探す 削除 数百パーツを手作業でとか・・・
  30. 30. #UE4 | @UNREALENGINE BlueprintやPythonを使うことでこれらの作業を自動化できる インポート 小さいパーツを探す 削除 自動化
  31. 31. #UE4 | @UNREALENGINE 小さいパーツを除外してインポート
  32. 32. #UE4 | @UNREALENGINE 小さいパーツを除外してインポート
  33. 33. #UE4 | @UNREALENGINE Blueprint ※拡大して解説していきます
  34. 34. #UE4 | @UNREALENGINE 解説 インポートするデータからDatasmith Sceneを構築
  35. 35. #UE4 | @UNREALENGINE Datasmith Scene Datasmithでは、実際にデータをインポートする前に メモリ上で一度シーン構築を行う インポート Datasmith Scene in Memory メモリ上でシーンを構築 CADデータ
  36. 36. #UE4 | @UNREALENGINE Datasmith Scene Datasmithでは、実際にデータをインポートする前に メモリ上で一度シーン構築を行う インポート Datasmith Scene in Memory メモリ上でシーンを構築 CADデータ
  37. 37. #UE4 | @UNREALENGINE 解説 Datasmith Scene内のアクタを取得
  38. 38. #UE4 | @UNREALENGINE 解説 バウンディングボックスの大きさを評価
  39. 39. #UE4 | @UNREALENGINE 解説 バウンディングボックス オブジェクトを囲む最小の立方体 この立方体の幅、奥行き、高さから オブジェクトの大体の大きさを測る
  40. 40. #UE4 | @UNREALENGINE 解説 条件に当てはまればアクタを削除
  41. 41. #UE4 | @UNREALENGINE 解説 インポートオプションを設定
  42. 42. #UE4 | @UNREALENGINE 解説 実際にインポートし、最後にDatasmith Sceneを削除
  43. 43. #UE4 | @UNREALENGINE 実装例:命名規則に応じたアセットリネーム
  44. 44. #UE4 | @UNREALENGINE 命名規則について アセットの種類や用途に応じて名前の前後に付ける文字列
  45. 45. #UE4 | @UNREALENGINE 命名規則について アセットの種類や用途に応じて名前の前後に付ける文字列 例えば・・・ Static Mesh アセット「Table」があるとしたら Static Meshの省略 SM を付け 「SM_Table」 バリエーションがある場合は 番号やアルファベットを付け「 SM_Table _A」にする
  46. 46. #UE4 | @UNREALENGINE 命名規則について 参考 Unreal Engine Assets Naming Convention https://wiki.unrealengine.com/Assets_Naming_Convention_JP
  47. 47. #UE4 | @UNREALENGINE 命名規則について プロジェクトが大規模化するにつれ、命名規則はより重要に
  48. 48. #UE4 | @UNREALENGINE 命名規則について プロジェクトが大規模化するにつれ、命名規則はより重要に 作業者が自由に名前を付けていると・・・ ● 他の作業者から見たとき用途や種類が判別しにくい ● 特定のアセットを探しずらい
  49. 49. #UE4 | @UNREALENGINE 実装例:命名規則に応じたアセットリネーム
  50. 50. #UE4 | @UNREALENGINE 解説 UI エディットできるText BoxやButtonなどを置いただけ シンプルな構成
  51. 51. #UE4 | @UNREALENGINE 解説 UI エディットできるText BoxやButtonなどを置いただけ シンプルな構成
  52. 52. #UE4 | @UNREALENGINE 解説 Blueprint
  53. 53. #UE4 | @UNREALENGINE 解説 Blueprint ボタンが押されたら選択しているアセットを取得
  54. 54. #UE4 | @UNREALENGINE 解説 Blueprint アセットの種類毎にリネーム処理
  55. 55. #UE4 | @UNREALENGINE 解説 Blueprint 関数Asset Renameの中身
  56. 56. #UE4 | @UNREALENGINE 解説 Blueprint 処理するクラスを設定
  57. 57. #UE4 | @UNREALENGINE 解説 Blueprint リネーム処理
  58. 58. #UE4 | @UNREALENGINE 実装例:Pythonによるインスタンシング
  59. 59. #UE4 | @UNREALENGINE インスタンシング 大量のオブジェクトを描画する際に有効な手法 ドローコールを削減し、描画コストを下げる ドローコール 現在の画面を描画するために必要な情報を呼び出す命令のこと 回数が多いほど処理負荷につながる可能性がある
  60. 60. #UE4 | @UNREALENGINE インスタンス化によるドローコールの削減 非インスタンス インスタンス 9回分のドローコール 1回分のドローコール
  61. 61. #UE4 | @UNREALENGINE Instanced Static Mesh Unreal Engineでのインスタンス化メッシュ
  62. 62. #UE4 | @UNREALENGINE Instanced Static Mesh
  63. 63. #UE4 | @UNREALENGINE Instanced Static Mesh • Static Mesh
  64. 64. #UE4 | @UNREALENGINE Instanced Static Mesh • Static Mesh • インスタンス数分の位置、回転、スケール
  65. 65. #UE4 | @UNREALENGINE Static Meshをインスタンス化 ツールやスクリプトを使わずに 手作業で変換しようとすると・・・ アクタ一つ一つの位置、回転、 スケールをコピーして・・・
  66. 66. #UE4 | @UNREALENGINE Static Meshをインスタンス化 ツールやスクリプトを使わずに 手作業で変換しようとすると・・・ インスタンスに追加
  67. 67. #UE4 | @UNREALENGINE Static Meshをインスタンス化 Merge Actors 選択アクタを一つのインスタンスに変換
  68. 68. #UE4 | @UNREALENGINE Static Meshをインスタンス化 Merge Actors 選択アクタを一つのインスタンスに変換 複数インスタンスを一度に生成はできない
  69. 69. #UE4 | @UNREALENGINE Static Meshをインスタンス化 Merge Actors 多数のアクタがあるとして・・・
  70. 70. #UE4 | @UNREALENGINE Static Meshをインスタンス化 Merge Actors 複数グループに分けてインスタンス化したい場合 インスタンス化したいグループ毎に 選択して変換する作業が必要
  71. 71. #UE4 | @UNREALENGINE インスタンス化によるドローコールの削減 大量のアクタを複数インスタンス化していくのは高コスト なるべく自動で、いい感じのグループに分けてインスタンス化したい・・・
  72. 72. #UE4 | @UNREALENGINE インスタンス化によるドローコールの削減 大量のアクタを複数インスタンス化していくのは高コスト なるべく自動で、いい感じのグループに分けてインスタンス化したい・・・ Python外部ライブラリからK-means法を使ってインスタンシング!
  73. 73. #UE4 | @UNREALENGINE K-means法とは ざっくり解説 クラスタ分析を行う手法の一つ Pythonの外部ライブラリScikit Learnに含まれている
  74. 74. #UE4 | @UNREALENGINE K-means法とは ざっくり解説 バラバラな座標のリストがあるとして・・・
  75. 75. #UE4 | @UNREALENGINE K-means法とは ざっくり解説 クラスタ数=5 設定したクラスタ数に応じて、近い属性同士のグループを作る
  76. 76. #UE4 | @UNREALENGINE Unreal Pythonで外部ライブラリを使う ライブラリインストール後、PythonLibsite-packagesを EngineBinariesThirdPartyPythonWin64Lib以下に丸ごとコピー import 〇〇でインポート出来るようになる
  77. 77. #UE4 | @UNREALENGINE K-means法によるインスタンシング
  78. 78. #UE4 | @UNREALENGINE コード 1/2 import unreal import numpy as np import sklearn from sklearn.cluster import KMeans bp_instance = unreal.EditorAssetLibrary.load_blueprint_class('/Game/BP_Instance.BP_Instance') list_actors = unreal.EditorLevelLibrary.get_selected_level_actors() list_static_mesh_actors = unreal.EditorFilterLibrary.by_class(list_actors,unreal.StaticMeshActor) list_unique = np.array([]) for lsm in list_static_mesh_actors: static_mesh = lsm.get_component_by_class(unreal.StaticMeshComponent).get_editor_property("StaticMesh") list_unique = np.append(list_unique,static_mesh) list_unique = np.unique(list_unique) for lu in list_unique: list_transform = np.array([]) list_locations = np.array([[0,0,0]])
  79. 79. #UE4 | @UNREALENGINE コード 2/2 for lsm in list_static_mesh_actors: if lsm.get_component_by_class(unreal.StaticMeshComponent).get_editor_property("StaticMesh") == lu: list_transform = np.append(list_transform,lsm.get_actor_transform()) location = np.array([[lsm.get_actor_location().x,lsm.get_actor_location().y,lsm.get_actor_location().z]]) list_locations = np.append(list_locations,location,axis=0) list_locations = np.delete(list_locations,0,axis=0) num_clusters = 3 pred = KMeans(n_clusters=num_clusters).fit_predict(list_locations) instanced_components = np.array([]) for i in range(num_clusters): instanced_actor = unreal.EditorLevelLibrary.spawn_actor_from_class(bp_instance,(0,0,0),(0,0,0)) instanced_component = instanced_actor.get_component_by_class(unreal.InstancedStaticMeshComponent) instanced_components = np.append(instanced_components,instanced_component) for j, pd in enumerate(pred): instanced_components[pd].add_instance(list_transform[j]) for k in range(num_clusters): instanced_components[k].set_editor_property("StaticMesh",lu) for lsm in list_static_mesh_actors: lsm.destroy_actor()
  80. 80. #UE4 | @UNREALENGINE 解説 1/5 #ライブラリをインポート import unreal import numpy as np import sklearn from sklearn.cluster import KMeans #インスタンス用のクラスをロード bp_instance = unreal.EditorAssetLibrary.load_blueprint_class('/Game/BP_Instance.BP_Instance') #選択しているアクタを取得 list_actors = unreal.EditorLevelLibrary.get_selected_level_actors() list_static_mesh_actors = unreal.EditorFilterLibrary.by_class(list_actors,unreal.StaticMeshActor)
  81. 81. #UE4 | @UNREALENGINE 解説 1/5 #ライブラリをインポート import unreal import numpy as np import sklearn from sklearn.cluster import KMeans #インスタンス用のクラスをロード bp_instance = unreal.EditorAssetLibrary.load_blueprint_class('/Game/BP_Instance.BP_Instance') #選択しているアクタを取得 list_actors = unreal.EditorLevelLibrary.get_selected_level_actors() list_static_mesh_actors = unreal.EditorFilterLibrary.by_class(list_actors,unreal.StaticMeshActor)
  82. 82. #UE4 | @UNREALENGINE 解説 1/5 #ライブラリをインポート import unreal import numpy as np import sklearn from sklearn.cluster import KMeans #インスタンス用のクラスをロード bp_instance = unreal.EditorAssetLibrary.load_blueprint_class('/Game/BP_Instance.BP_Instance') #選択しているアクタを取得 list_actors = unreal.EditorLevelLibrary.get_selected_level_actors() list_static_mesh_actors = unreal.EditorFilterLibrary.by_class(list_actors,unreal.StaticMeshActor)
  83. 83. #UE4 | @UNREALENGINE 解説 1/5 #ライブラリをインポート import unreal import numpy as np import sklearn from sklearn.cluster import KMeans #インスタンス用のクラスをロード bp_instance = unreal.EditorAssetLibrary.load_blueprint_class('/Game/BP_Instance.BP_Instance') #選択しているアクタを取得 list_actors = unreal.EditorLevelLibrary.get_selected_level_actors() list_static_mesh_actors = unreal.EditorFilterLibrary.by_class(list_actors,unreal.StaticMeshActor) 後で選択アクタから 位置、回転、メッシュ情報などを取得
  84. 84. #UE4 | @UNREALENGINE 解説 2/5 #メッシュの種類毎にクラスタリングするため、アクタのリストからメッシュの種類がいくつあるかを求める list_unique = np.array([]) for lsm in list_static_mesh_actors: static_mesh = lsm.get_component_by_class(unreal.StaticMeshComponent).get_editor_property("StaticMesh") list_unique = np.append(list_unique,static_mesh) list_unique = np.unique(list_unique) #インスタンスに追加するトランスフォームリストと、クラスタリングに使うための位置リストを作成 for lu in list_unique: list_transform = np.array([]) list_locations = np.array([[0,0,0]])
  85. 85. #UE4 | @UNREALENGINE 複数種類のメッシュがあった場合 Instanced Static Meshが 持てるメッシュは一種類のみ
  86. 86. #UE4 | @UNREALENGINE 複数種類のメッシュがあった場合 クラスタ数=3
  87. 87. #UE4 | @UNREALENGINE 複数種類のメッシュがあった場合 種類ごとにクラスタリング クラスタ数=3
  88. 88. #UE4 | @UNREALENGINE 複数種類のメッシュがあった場合 クラスタ数=3 種類ごとにクラスタリング
  89. 89. #UE4 | @UNREALENGINE 解説 3/5 #インスタンスに追加するトランスフォームリストと、クラスタリングに使うための位置リストを作成 for lsm in list_static_mesh_actors: if lsm.get_component_by_class(unreal.StaticMeshComponent).get_editor_property("StaticMesh") == lu: list_transform = np.append(list_transform,lsm.get_actor_transform()) location = np.array([[lsm.get_actor_location().x,lsm.get_actor_location().y,lsm.get_actor_location().z]]) list_locations = np.append(list_locations,location,axis=0) list_locations = np.delete(list_locations,0,axis=0) #クラスタリング num_clusters = 3 pred = KMeans(n_clusters=num_clusters).fit_predict(list_locations)
  90. 90. #UE4 | @UNREALENGINE 解説 3/5 #インスタンスに追加するトランスフォームリストと、クラスタリングに使うための位置リストを作成 for lsm in list_static_mesh_actors: if lsm.get_component_by_class(unreal.StaticMeshComponent).get_editor_property("StaticMesh") == lu: list_transform = np.append(list_transform,lsm.get_actor_transform()) location = np.array([[lsm.get_actor_location().x,lsm.get_actor_location().y,lsm.get_actor_location().z]]) list_locations = np.append(list_locations,location,axis=0) list_locations = np.delete(list_locations,0,axis=0) #クラスタリング num_clusters = 3 pred = KMeans(n_clusters=num_clusters).fit_predict(list_locations)
  91. 91. #UE4 | @UNREALENGINE 解説 3/5 #インスタンスに追加するトランスフォームリストと、クラスタリングに使うための位置リストを作成 for lsm in list_static_mesh_actors: if lsm.get_component_by_class(unreal.StaticMeshComponent).get_editor_property("StaticMesh") == lu: list_transform = np.append(list_transform,lsm.get_actor_transform()) location = np.array([[lsm.get_actor_location().x,lsm.get_actor_location().y,lsm.get_actor_location().z]]) list_locations = np.append(list_locations,location,axis=0) list_locations = np.delete(list_locations,0,axis=0) #クラスタリング num_clusters = 3 pred = KMeans(n_clusters=num_clusters).fit_predict(list_locations) Get_actor_location() ・・・Unreal Vector型を返す
  92. 92. #UE4 | @UNREALENGINE Unreal Vector型 Unreal Engine上でVector型をやり取りするための型 Kmeansでも使えるように
  93. 93. #UE4 | @UNREALENGINE 解説 3/5 #インスタンスに追加するトランスフォームリストと、クラスタリングに使うための位置リストを作成 for lsm in list_static_mesh_actors: if lsm.get_component_by_class(unreal.StaticMeshComponent).get_editor_property("StaticMesh") == lu: list_transform = np.append(list_transform,lsm.get_actor_transform()) location = np.array([[lsm.get_actor_location().x,lsm.get_actor_location().y,lsm.get_actor_location().z]]) list_locations = np.append(list_locations,location,axis=0) list_locations = np.delete(list_locations,0,axis=0) #クラスタリング num_clusters = 3 pred = KMeans(n_clusters=num_clusters).fit_predict(list_locations)
  94. 94. #UE4 | @UNREALENGINE 解説 3/5 #インスタンスに追加するトランスフォームリストと、クラスタリングに使うための位置リストを作成 for lsm in list_static_mesh_actors: if lsm.get_component_by_class(unreal.StaticMeshComponent).get_editor_property("StaticMesh") == lu: list_transform = np.append(list_transform,lsm.get_actor_transform()) location = np.array([[lsm.get_actor_location().x,lsm.get_actor_location().y,lsm.get_actor_location().z]]) list_locations = np.append(list_locations,location,axis=0) list_locations = np.delete(list_locations,0,axis=0) #クラスタリング num_clusters = 3 pred = KMeans(n_clusters=num_clusters).fit_predict(list_locations)
  95. 95. #UE4 | @UNREALENGINE 解説 3/5 #インスタンスに追加するトランスフォームリストと、クラスタリングに使うための位置リストを作成 for lsm in list_static_mesh_actors: if lsm.get_component_by_class(unreal.StaticMeshComponent).get_editor_property("StaticMesh") == lu: list_transform = np.append(list_transform,lsm.get_actor_transform()) location = np.array([[lsm.get_actor_location().x,lsm.get_actor_location().y,lsm.get_actor_location().z]]) list_locations = np.append(list_locations,location,axis=0) list_locations = np.delete(list_locations,0,axis=0) #クラスタリング num_clusters = 5 pred = KMeans(n_clusters=num_clusters).fit_predict(list_locations) n_clusters = 5
  96. 96. #UE4 | @UNREALENGINE 解説 3/5 #インスタンスに追加するトランスフォームリストと、クラスタリングに使うための位置リストを作成 for lsm in list_static_mesh_actors: if lsm.get_component_by_class(unreal.StaticMeshComponent).get_editor_property("StaticMesh") == lu: list_transform = np.append(list_transform,lsm.get_actor_transform()) location = np.array([[lsm.get_actor_location().x,lsm.get_actor_location().y,lsm.get_actor_location().z]]) list_locations = np.append(list_locations,location,axis=0) list_locations = np.delete(list_locations,0,axis=0) #クラスタリング num_clusters = 5 pred = KMeans(n_clusters=num_clusters).fit_predict(list_locations) 0 1 2 3 4 0 0 0 1 1 1 2 2 2 2 3 3 3 4 4 4 fit_predict
  97. 97. #UE4 | @UNREALENGINE 解説 4/5 #コンポーネントのリストを作成 instanced_components = np.array([]) #クラスタ毎にアクタをスポーン、コンポーネントをリストに入れる for i in range(num_clusters): instanced_actor = unreal.EditorLevelLibrary.spawn_actor_from_class(bp_instance,(0,0,0),(0,0,0)) instanced_component = instanced_actor.get_component_by_class(unreal.InstancedStaticMeshComponent) instanced_components = np.append(instanced_components,instanced_component)
  98. 98. #UE4 | @UNREALENGINE 解説 4/5 #コンポーネントのリストを作成 instanced_components = np.array([]) #クラスタ毎にアクタをスポーン、コンポーネントをリストに入れる for i in range(num_clusters): instanced_actor = unreal.EditorLevelLibrary.spawn_actor_from_class(bp_instance,(0,0,0),(0,0,0)) instanced_component = instanced_actor.get_component_by_class(unreal.InstancedStaticMeshComponent) instanced_components = np.append(instanced_components,instanced_component)
  99. 99. #UE4 | @UNREALENGINE 解説 4/5 #コンポーネントのリストを作成 instanced_components = np.array([]) #クラスタ毎にアクタをスポーン、コンポーネントをリストに入れる for i in range(num_clusters): instanced_actor = unreal.EditorLevelLibrary.spawn_actor_from_class(bp_instance,(0,0,0),(0,0,0)) instanced_component = instanced_actor.get_component_by_class(unreal.InstancedStaticMeshComponent) instanced_components = np.append(instanced_components,instanced_component)
  100. 100. #UE4 | @UNREALENGINE 解説 4/5 #コンポーネントのリストを作成 instanced_components = np.array([]) #クラスタ毎にアクタをスポーン、コンポーネントをリストに入れる for i in range(num_clusters): instanced_actor = unreal.EditorLevelLibrary.spawn_actor_from_class(bp_instance,(0,0,0),(0,0,0)) instanced_component = instanced_actor.get_component_by_class(unreal.InstancedStaticMeshComponent) instanced_components = np.append(instanced_components,instanced_component) スポーンするアクタは あらかじめ用意しておく Blueprintを作成し Instanced Static Meshを追加
  101. 101. #UE4 | @UNREALENGINE 解説 4/5 #コンポーネントのリストを作成 instanced_components = np.array([]) #クラスタ毎にアクタをスポーン、コンポーネントをリストに入れる for i in range(num_clusters): instanced_actor = unreal.EditorLevelLibrary.spawn_actor_from_class(bp_instance,(0,0,0),(0,0,0)) instanced_component = instanced_actor.get_component_by_class(unreal.InstancedStaticMeshComponent) instanced_components = np.append(instanced_components,instanced_component)
  102. 102. #UE4 | @UNREALENGINE 解説 5/5 #クラスタ番号を元に親となるインスタンスを選択し、トランスフォームを追加 for j, pd in enumerate(pred): instanced_components[pd].add_instance(list_transform[j]) #スタティックメッシュを割り当て for k in range(num_clusters): instanced_components[k].set_editor_property("StaticMesh",lu) #最初に選択していたアクタを削除 for lsm in list_static_mesh_actors: lsm.destroy_actor()
  103. 103. #UE4 | @UNREALENGINE 解説 5/5 #クラスタ番号を元に親となるインスタンスを選択し、トランスフォームを追加 for j, pd in enumerate(pred): instanced_components[pd].add_instance(list_transform[j]) #スタティックメッシュを割り当て for k in range(num_clusters): instanced_components[k].set_editor_property("StaticMesh",lu) #最初に選択していたアクタを削除 for lsm in list_static_mesh_actors: lsm.destroy_actor()
  104. 104. #UE4 | @UNREALENGINE 解説 5/5 #クラスタ番号を元に親となるインスタンスを選択し、トランスフォームを追加 for j, pd in enumerate(pred): instanced_components[pd].add_instance(list_transform[j]) #スタティックメッシュを割り当て for k in range(num_clusters): instanced_components[k].set_editor_property("StaticMesh",lu) #最初に選択していたアクタを削除 for lsm in list_static_mesh_actors: lsm.destroy_actor() 空のインスタンス
  105. 105. #UE4 | @UNREALENGINE 解説 5/5 #クラスタ番号を元に親となるインスタンスを選択し、トランスフォームを追加 for j, pd in enumerate(pred): instanced_components[pd].add_instance(list_transform[j]) #スタティックメッシュを割り当て for k in range(num_clusters): instanced_components[k].set_editor_property("StaticMesh",lu) #最初に選択していたアクタを削除 for lsm in list_static_mesh_actors: lsm.destroy_actor()
  106. 106. #UE4 | @UNREALENGINE 解説 5/5 #クラスタ番号を元に親となるインスタンスを選択し、トランスフォームを追加 for j, pd in enumerate(pred): instanced_components[pd].add_instance(list_transform[j]) #スタティックメッシュを割り当て for k in range(num_clusters): instanced_components[k].set_editor_property("StaticMesh",lu) #最初に選択していたアクタを削除 for lsm in list_static_mesh_actors: lsm.destroy_actor()
  107. 107. #UE4 | @UNREALENGINE 解説 5/5 #クラスタ番号を元に親となるインスタンスを選択し、トランスフォームを追加 for j, pd in enumerate(pred): instanced_components[pd].add_instance(list_transform[j]) #スタティックメッシュを割り当て for k in range(num_clusters): instanced_components[k].set_editor_property("StaticMesh",lu) #最初に選択していたアクタを削除 for lsm in list_static_mesh_actors: lsm.destroy_actor()
  108. 108. #UE4 | @UNREALENGINE これでインスタンス化できたが・・・ 再調整したい場合は元のバラバラな状態に戻す必要がある
  109. 109. #UE4 | @UNREALENGINE 実装例:インスタンスを個別のStaticMeshに変換
  110. 110. #UE4 | @UNREALENGINE インスタンスを個別のStaticMeshに変換
  111. 111. #UE4 | @UNREALENGINE コード import unreal import numpy as np selected_actors = unreal.EditorLevelLibrary.get_selected_level_actors() for sa in selected_actors: instanced_components = np.array([]) instanced_component = sa.get_components_by_class(unreal.InstancedStaticMeshComponent) instanced_components = np.append(instanced_components,instanced_component) for ic in instanced_components: instance_transform = np.array([]) instance_count = ic.get_instance_count() for j in range(instance_count): instance_transform = np.append(instance_transform,ic.get_instance_transform(j,1)) spawned_actor = unreal.EditorLevelLibrary.spawn_actor_from_class(unreal.StaticMeshActor,(0,0,0),(0,0,0)) spawned_actor.set_actor_transform(instance_transform[j],0,0) smc = spawned_actor.get_component_by_class(unreal.StaticMeshComponent) smc.set_editor_property("StaticMesh",ic.get_editor_property("StaticMesh")) for sa in selected_actors: sa.destroy_actor()
  112. 112. #UE4 | @UNREALENGINE 解説 1/3 #ライブラリをインポート import unreal import numpy as np #選択したアクタを取得 selected_actors = unreal.EditorLevelLibrary.get_selected_level_actors()
  113. 113. #UE4 | @UNREALENGINE 解説 1/3 #ライブラリをインポート import unreal import numpy as np #選択したアクタを取得 selected_actors = unreal.EditorLevelLibrary.get_selected_level_actors()
  114. 114. #UE4 | @UNREALENGINE 解説 1/3 #ライブラリをインポート import unreal import numpy as np #選択したアクタを取得 selected_actors = unreal.EditorLevelLibrary.get_selected_level_actors()
  115. 115. #UE4 | @UNREALENGINE 解説 2/3 #インスタンスコンポーネントを配列に入れる for sa in selected_actors: instanced_components = np.array([]) instanced_component = sa.get_components_by_class(unreal.InstancedStaticMeshComponent) instanced_components = np.append(instanced_components,instanced_component) #インスタンス数を取得 for ic in instanced_components: instance_transform = np.array([]) instance_count = ic.get_instance_count()
  116. 116. #UE4 | @UNREALENGINE 解説 2/3 #インスタンスコンポーネントを配列に入れる for sa in selected_actors: instanced_components = np.array([]) instanced_component = sa.get_components_by_class(unreal.InstancedStaticMeshComponent) instanced_components = np.append(instanced_components,instanced_component) #インスタンス数を取得 for ic in instanced_components: instance_transform = np.array([]) instance_count = ic.get_instance_count()
  117. 117. #UE4 | @UNREALENGINE 解説 2/3 #インスタンスコンポーネントを配列に入れる for sa in selected_actors: instanced_components = np.array([]) instanced_component = sa.get_components_by_class(unreal.InstancedStaticMeshComponent) instanced_components = np.append(instanced_components,instanced_component) #インスタンス数を取得 for ic in instanced_components: instance_transform = np.array([]) instance_count = ic.get_instance_count()
  118. 118. #UE4 | @UNREALENGINE 解説 2/3 #インスタンスコンポーネントを配列に入れる for sa in selected_actors: instanced_components = np.array([]) instanced_component = sa.get_components_by_class(unreal.InstancedStaticMeshComponent) instanced_components = np.append(instanced_components,instanced_component) #インスタンス数を取得 for ic in instanced_components: instance_transform = np.array([]) instance_count = ic.get_instance_count() インスタンスがいくつあるか取得し、 その数分新たにアクタをスポーンしていく
  119. 119. #UE4 | @UNREALENGINE 解説 3/3 #インスタンス数の分だけトランスフォーム値を取得 for j in range(instance_count): instance_transform = np.append(instance_transform,ic.get_instance_transform(j,1)) #スポーンしてトランスフォームを適用 spawned_actor = unreal.EditorLevelLibrary.spawn_actor_from_class(unreal.StaticMeshActor,(0,0,0),(0,0,0)) spawned_actor.set_actor_transform(instance_transform[j],0,0) smc = spawned_actor.get_component_by_class(unreal.StaticMeshComponent) #スタティックメッシュを割り当て smc.set_editor_property("StaticMesh",ic.get_editor_property("StaticMesh")) #最初に選択していたアクタを削除 for sa in selected_actors: sa.destroy_actor()
  120. 120. #UE4 | @UNREALENGINE 解説 3/3 #インスタンス数の分だけトランスフォーム値を取得 for j in range(instance_count): instance_transform = np.append(instance_transform,ic.get_instance_transform(j,1)) #スポーンしてトランスフォームを適用 spawned_actor = unreal.EditorLevelLibrary.spawn_actor_from_class(unreal.StaticMeshActor,(0,0,0),(0,0,0)) spawned_actor.set_actor_transform(instance_transform[j],0,0) smc = spawned_actor.get_component_by_class(unreal.StaticMeshComponent) #スタティックメッシュを割り当て smc.set_editor_property("StaticMesh",ic.get_editor_property("StaticMesh")) #最初に選択していたアクタを削除 for sa in selected_actors: sa.destroy_actor()
  121. 121. #UE4 | @UNREALENGINE 解説 3/3 #インスタンス数の分だけトランスフォーム値を取得 for j in range(instance_count): instance_transform = np.append(instance_transform,ic.get_instance_transform(j,1)) #スポーンしてトランスフォームを適用 spawned_actor = unreal.EditorLevelLibrary.spawn_actor_from_class(unreal.StaticMeshActor,(0,0,0),(0,0,0)) spawned_actor.set_actor_transform(instance_transform[j],0,0) #スタティックメッシュを割り当て smc = spawned_actor.get_component_by_class(unreal.StaticMeshComponent) smc.set_editor_property("StaticMesh",ic.get_editor_property("StaticMesh")) #最初に選択していたアクタを削除 for sa in selected_actors: sa.destroy_actor()
  122. 122. #UE4 | @UNREALENGINE 解説 3/3 #インスタンス数の分だけトランスフォーム値を取得 for j in range(instance_count): instance_transform = np.append(instance_transform,ic.get_instance_transform(j,1)) #スポーンしてトランスフォームを適用 spawned_actor = unreal.EditorLevelLibrary.spawn_actor_from_class(unreal.StaticMeshActor,(0,0,0),(0,0,0)) spawned_actor.set_actor_transform(instance_transform[j],0,0) #スタティックメッシュを割り当て smc = spawned_actor.get_component_by_class(unreal.StaticMeshComponent) smc.set_editor_property("StaticMesh",ic.get_editor_property("StaticMesh")) #最初に選択していたアクタを削除 for sa in selected_actors: sa.destroy_actor()
  123. 123. #UE4 | @UNREALENGINE 解説 3/3 #インスタンス数の分だけトランスフォーム値を取得 for j in range(instance_count): instance_transform = np.append(instance_transform,ic.get_instance_transform(j,1)) #スポーンしてトランスフォームを適用 spawned_actor = unreal.EditorLevelLibrary.spawn_actor_from_class(unreal.StaticMeshActor,(0,0,0),(0,0,0)) spawned_actor.set_actor_transform(instance_transform[j],0,0) #スタティックメッシュを割り当て smc = spawned_actor.get_component_by_class(unreal.StaticMeshComponent) smc.set_editor_property("StaticMesh",ic.get_editor_property("StaticMesh")) #最初に選択していたアクタを削除 for sa in selected_actors: sa.destroy_actor()
  124. 124. #UE4 | @UNREALENGINE おまけ:UIを作る
  125. 125. #UE4 | @UNREALENGINE おまけ:UIを作る
  126. 126. #UE4 | @UNREALENGINE おまけ:UIを作る 特定のアクタを選択
  127. 127. #UE4 | @UNREALENGINE おまけ:UIを作る 特定のアクタを選択
  128. 128. #UE4 | @UNREALENGINE おまけ:UIを作る
  129. 129. #UE4 | @UNREALENGINE 実装例は後日Git Hubなどで公開予定 ※あくまで一例として作ったものなので、より実用的にするには改良が必要 ※公開した実装例の保守、サポートは致しません
  130. 130. #UE4 | @UNREALENGINE 参考 Unreal Python API リファレンス https://api.unrealengine.com/INT/PythonAPI/
  131. 131. #UE4 | @UNREALENGINE 参考 Mclarenによる事例:ホワイトペーパー Unreal Studio を使用した CAD データの準備および リアルタイム ビジュアライゼーションでの自動化 https://cdn2.unrealengine.com/Unreal+Engine%2Fresources%2FMcLaren+W hitepaper%2FADCaV-Whitepaper-JPN-V2- f4fd0b09e8b279171149eef9220370e1b7495092.pdf
  132. 132. #UE4 | @UNREALENGINE ご清聴ありがとうございました

×