@@ -359,6 +359,7 @@ namespace {
359359 }
360360
361361 UPrefabricatorAsset* PrefabAsset = Cast<UPrefabricatorAsset>(PrefabActor->PrefabComponent ->PrefabAssetInterface .LoadSynchronous ());
362+ USceneComponent* SceneComponent = Cast<USceneComponent>(ObjToSerialize);
362363
363364 if (!PrefabAsset) {
364365 return ;
@@ -531,12 +532,28 @@ void FPrefabTools::LoadActorState(AActor* InActor, const FPrefabricatorActorData
531532 for (const FPrefabricatorComponentData& ComponentData : InActorData.Components ) {
532533 if (UActorComponent** SearchResult = ComponentsByName.Find (ComponentData.ComponentName )) {
533534 UActorComponent* Component = *SearchResult;
535+ USceneComponent* SceneComponent = Cast<USceneComponent>(Component);
536+
537+ // JB: We store the world location in case we would be restoring a component simulating physics.
538+ // JB: This is necessary only for prefab spawned at runtime.
539+ FVector WorldLocation = FVector::ZeroVector;
540+ if (InActor->HasActorBegunPlay ()) {
541+ if (SceneComponent)
542+ {
543+ WorldLocation = SceneComponent->GetComponentLocation ();
544+ }
545+ }
546+
534547 bool bPreviouslyRegister;
535548 {
536549 // SCOPE_CYCLE_COUNTER(STAT_LoadStateFromPrefabAsset_UnregisterComponent);
537550 bPreviouslyRegister = Component->IsRegistered ();
538551 if (InSettings.bUnregisterComponentsBeforeLoading && bPreviouslyRegister) {
539552 Component->UnregisterComponent ();
553+ // JB: Some of the components (e.g., UPhysicsConstraintComponent) also require re-initialization.
554+ if (Component->HasBeenInitialized ()) {
555+ Component->UninitializeComponent ();
556+ }
540557 }
541558 }
542559
@@ -548,7 +565,14 @@ void FPrefabTools::LoadActorState(AActor* InActor, const FPrefabricatorActorData
548565 {
549566 // SCOPE_CYCLE_COUNTER(STAT_LoadStateFromPrefabAsset_RegisterComponent);
550567 if (InSettings.bUnregisterComponentsBeforeLoading && bPreviouslyRegister) {
568+ // JB: Register component will also initialize component if necessary.
551569 Component->RegisterComponent ();
570+ // JB: Components that are simulating physics are detached from the actor on register.
571+ // JB: Restoring their relative location above will cause them to be spawned at a wrong location so we fix it.
572+ // JB: This is necessary only for prefab spawned at runtime.
573+ if (InActor->HasActorBegunPlay () && SceneComponent->IsSimulatingPhysics ()) {
574+ SceneComponent->SetRelativeLocation (WorldLocation);
575+ }
552576 }
553577 }
554578 }
@@ -696,7 +720,8 @@ void FPrefabTools::LoadStateFromPrefabAsset(APrefabActor* PrefabActor, const FPr
696720 }
697721
698722 // JB: Spawning actors on top of each other may cause problems with PhysicX (as it needs to compute the overlaps).
699- ChildActor = Service->SpawnActor (ActorClass, PrefabActor->GetActorTransform (), PrefabActor->GetLevel (), Template);
723+ FTransform WorldTransform = ActorItemData.RelativeTransform * PrefabActor->GetTransform ();
724+ ChildActor = Service->SpawnActor (ActorClass, WorldTransform, PrefabActor->GetLevel (), Template);
700725 if (!Template) {
701726 LoadActorState (ChildActor, ActorItemData, InSettings);
702727 if (InState.IsValid ()) {
0 commit comments