UE5.1からアクターを生成する時に与えるパラメータFActorSpawnParametersにCustomPreSpawnInitalizationメンバが追加されました。
アクター生成時にBeginPlayが呼ばれるより前にパラメータをセットしておく方法は、ブループリントだとプロパティのExpose on Spawnにチェックを入れる、c++であればUWorld::SpawnActorDeferredでアクターを作成した後にパラメータをセットしてUGameplayStatics::FinishSpawningActorを呼び出すといった方法がありますが、CustomPreSpawnInitalizationはそれより早い段階でアクターを操作できることが特徴です。
アクターの生成処理の流れ
アクターが生まれる時の処理の流れはこちらで解説されています。
以下は一部を拝借して少し追加したものです。
- SpawnActorが呼び出される
- NewObject
- コンストラクターの実行
- PostInitProperties
- CustomPreSpawnInitalization
- PostSpawnInitialize
- RegisterAllComponents (ルートコンポーネントがc++で定義されている場合)
- PostActorCreated
- (SpawnActorDeferredを呼び出した場合はこのタイミングでユーザーコードを実行)
- ExecuteConstruction:
- OnConstruction
- PostActorConstruction:
- PreInitializeComponents
- InitializeComponent
- PostInitializeComponents
- OnActorSpawned
- BeginPlay
CustomPreSpawnInitalizationはNewObjectが終わった後にすぐに呼び出されるため、特にRegisterAllComponentsの前にパラメータをセットしたい場合に威力を発揮します。
使い方
CustomPreSpawnInititalizationの型は TFunction<void(AActor*)> となっているのでラムダなどの形でユーザーコードを実行することができます。
以下の例はGeometryCollectionComponentを持つアクターを生成し、そのRestCollectionに任意のアセットを設定しています。
GeometryCollectionComponentはRegisterComponentが呼び出されるタイミングで適切なRestCollectionが設定されている必要があるため、CustomPreSpawnInitalizationを利用することが有効です。
void UMyBlueprintFunctionLibrary::SpawnGC(const UObject* WorldContextObject, TSubclassOf<AActor> ActorClass, UGeometryCollection* InRestCollection, FTransform InTransform)
{
if (UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::ReturnNull))
{
FActorSpawnParameters Parameter;
Parameter.CustomPreSpawnInitalization = [&](AActor* Actor)
{
UGeometryCollectionComponent* Component = Actor->FindComponentByClass<UGeometryCollectionComponent>();
if( Component )
{
Component->SetRestCollection( InRestCollection );
}
};
World->SpawnActor<AActor>( *ActorClass, InTransform, Parameter );
}
}