1
0

More than 3 years have passed since last update.

FStringからブループリントをSpawnする

Posted at

UnrealEngineでは、ブループリントの変数や関数にアクセスするには、キャストを行う必要があるかと思います。
ブループリント自体が、Classである為、当たり前の事ですが、ブループリントはどちらかというと、
システム的な振る舞いではなく、必要な機能の集合(UnityのPrefabのような扱い方)として、ブループリントを量産したい場合があります。
それらをスポーンする際に、必要なClassをGetAllActorsClass等で探してきてブループリントのキャストをスポーンするというのが、とても面倒だったという事がありました。

スポーンアクタ.png

上記のノードは、UnrealEngineにおいて、ブループリントからActorをスポーンする事のできる、最も一般的なノードです。
先ほども記載しましたが、このノードでActorをスポーンする為には、GetAllActors系のノードから明確なClassの特定が必要になっています。
例えば、ブループリント名からそのClassの参照の取得やActor化ができないかと考え、調査したメモになります。

環境

UnrealEngine 4.26.2で検証しています。
また、Runtimeでの動作ではなく、Editor時での動作のみを念頭においています。

実現方法

実現するにあたって、方法を二通り考えました。

  • AssetDataを見つける
  • Stringからオブジェクト参照やClass参照を得る

AssetDataを見つける

この方法は、簡単で分かりやすいですが、負荷もかかり泥臭い方法です。
具体的な方法としては、AssetRegistryのGetAssetsから、名前一致でAssetDataを見つけるという方法です。
例えば、下に載せるようなノードで実現できます。ResultAssetが見つけたClassの参照になります。
AssetDataを取得できている為、そのままActorからスポーンする事も可能です。
注意点として、リストを上から見て、目的のAssetを探すという方法である為、フィルタリングをかけて、検索対象になるClassの数を減らす必要があります。
例として上げたノードでは、「Blueprint」のクラスでフィルタリングしています。

AssetDataを見つけてレベルに配置する.png

Stringからオブジェクト参照を得る

続けて、文字列からActorのインスタンス化を行ってみます。
ブループリントのクラス名だと、AssetDataを探す事しか出来ませんが、ObjectPathからオブジェクト参照にキャストする事ができます。
ObjectPathは、フォーマットが決まっている為、生成する事も可能です。

文字列からオブジェクト参照を取得する.png

以下のノードを試してみます。

ObjectPathからレベルに配置.png

成功しました。

オブジェクト参照をレベルに配置成功例.png

また、キャストをしなくとも、ObjectPathから直接、オブジェクト参照を取得するノードが実装されていました。

LoadAssetノード.png

こちらのLoadAssetノードでも同じ結果が得られます。

LoadAssetノードの使い方.png

StringからClass参照を得る

オブジェクト参照でのスポーンが上手くいった為、Classからのスポーンも期待できそうです。
本来、実現したかったのがこちらの方法になります。
オブジェクト参照をキャストした時と同じように、ObjectPathからClass参照をキャストします。
こちらのノードを使う事で、StringからClass参照を取得する事ができます。

文字列からClass参照を取得する?.png

ノードを組んでみます。

image.png

では、これは上手く行くのか、実行してみます。

ObjectPathからClass参照を取得した結果.png

何も表示されません。調査してみます。

StringからClass参照を得る(原因調査)

PrintStringで出したログを見てみます。

ObjectPathからClass参照を取得のアウトプットログ.png

すると、以下のエラーが発生しました。

LogStats: FPlatformStackWalk::StackWalkAndDump -  0.624 s
LogOutputDevice: Error: === Handled ensure: ===
LogOutputDevice: Error: Ensure condition failed: !FPackageName::IsShortPackageName(Path) [File:D:/Build/++UE4/Sync/Engine/Source/Runtime/CoreUObject/Private/UObject/SoftObjectPath.cpp] [Line: 79]
LogOutputDevice: Error: Cannot create SoftObjectPath with short package name 'TestClassA'! You must pass in fully qualified package names
LogOutputDevice: Error: Stack: 
LogOutputDevice: Error: [Callstack] 0x00007ffe1cca1909 UE4Editor-CoreUObject.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe1cb78b7c UE4Editor-CoreUObject.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe1c795810 UE4Editor-CoreUObject.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe1c79554e UE4Editor-CoreUObject.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffde2846959 UE4Editor-Engine.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffde3500664 UE4Editor-Engine.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe1cb8ae84 UE4Editor-CoreUObject.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe1cb8d061 UE4Editor-CoreUObject.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe1cb622fd UE4Editor-CoreUObject.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe1cb36b6a UE4Editor-CoreUObject.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe1cb61ef1 UE4Editor-CoreUObject.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe1cb622fd UE4Editor-CoreUObject.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe1cb61704 UE4Editor-CoreUObject.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe1c8d2604 UE4Editor-CoreUObject.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe1cb60e63 UE4Editor-CoreUObject.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe0740208b UE4Editor-UMG.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe07531637 UE4Editor-UMG.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe0749a103 UE4Editor-UMG.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe24b9859e UE4Editor-Slate.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe24bb071e UE4Editor-Slate.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe249f46be UE4Editor-Slate.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe24a77f14 UE4Editor-Slate.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe24a60337 UE4Editor-Slate.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe24a53632 UE4Editor-Slate.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe585dbcb5 UE4Editor-ApplicationCore.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe585c9197 UE4Editor-ApplicationCore.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe585de389 UE4Editor-ApplicationCore.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe585c4310 UE4Editor-ApplicationCore.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe7c33e858 USER32.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe7c33e299 USER32.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe585df914 UE4Editor-ApplicationCore.dll!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ff69bc28848 UE4Editor.exe!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ff69bc4117c UE4Editor.exe!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ff69bc4125a UE4Editor.exe!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ff69bc552bd UE4Editor.exe!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ff69bc57fea UE4Editor.exe!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe7af57034 KERNEL32.DLL!UnknownFunction []
LogOutputDevice: Error: [Callstack] 0x00007ffe7cca2651 ntdll.dll!UnknownFunction []
LogStats:                SubmitErrorReport -  0.000 s
LogStats:                    SendNewReport - 12.710 s
LogStats:             FDebug::EnsureFailed - 13.341 s
LogScript: Error: D:/Build/++UE4/Sync/Engine/Source/Runtime/Engine/Private/KismetSystemLibrary.cpp(1045): Runtime Error: "MakeSoftClassPathで無効なオブジェクトパス TestClassA。"
LogScript: Error: Script Msg: MakeSoftClassPathで無効なオブジェクトパス TestClassA。
LogScript: Error: Script call stack:
    StringToClassTool_C.ExecuteUbergraph_StringToClassTool
    StringToClassTool_C.BndEvt__StringToClassTool_Button_0_K2Node_ComponentBoundEvent_0_OnButtonClickedEvent__DelegateSignature
LogUObjectHash: Compacting FUObjectHashTables data took   9.01ms

何が問題であったか

原因は、以下の部分にあるかと思います。

LogOutputDevice: Error: Cannot create SoftObjectPath with short package name 'TestClassA'! You must pass in fully qualified package names

Class名を渡してみる


LogScript: Error: D:/Build/++UE4/Sync/Engine/Source/Runtime/Engine/Private/KismetSystemLibrary.cpp(1045): Runtime Error: "MakeSoftClassPathで無効なオブジェクトパス TestClassA。"
LogScript: Error: Script Msg: MakeSoftClassPathで無効なオブジェクトパス TestClassA。
LogScript: Error: Script call stack:
    StringToClassTool_C.ExecuteUbergraph_StringToClassTool
    StringToClassTool_C.BndEvt__StringToClassTool_Button_0_K2Node_ComponentBoundEvent_4_OnButtonClickedEvent__DelegateSignature
LogBlueprintUserMessages: [StringToClassTool_C_1] SoftClassReferenceを存在しない

MakeSoftClassPathでパスが無効という事で、ObjectPathを渡してみる。

LogBlueprintUserMessages: [StringToClassTool_C_4] SoftClassReferenceが存在する
LogBlueprintUserMessages: [StringToClassTool_C_4] ClassReferenceを存在しない

SoftClassReferenceまでは、取得する事ができた。

LoadBlueprintClassノードとLoadClassAssetBlockingノード

他に方法がないか調べたところ、目的のノードが実装されてました。
「LoadBlueprintClassノード」と「LoadClassAssetBlockingノード」になります。

LoadBlueprintClassノード
LoadBlueprintClassノード.png

LoadClassAssetBlockingノード
LoadClassAssetBlockingノード.png

それぞれ、テスト用のノードを組みテストしてみます。

LoadBlueprintClassノードのテスト
LoadBlueprintClassノードのテスト.png

LoadClassAssetBlockingノード
LoadClassAssetBlockingノードのテスト.png

画像にも記載してある通り、LoadBlueprintClassノードのテストは上手く行きました。

結論

  • StringのClass名から直接オブジェクト化やClass参照を取得はできないが、ObjectPathからは可能
  • ObjectPathで、オブジェクトを取得したい場合は、LoadAssetを使用する
  • ObjectPathで、Class参照を取得したい場合は、LoadBlueprintClassノードを使用する
  • ObjectPathも分からず、手掛かりがClass名しか分からない場合は、AssetDataで探す
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0