Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disables the serialization of RelativeLocation for root components. #22

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,22 @@ namespace {
}
}

// JB: We skip serialization of RelativeLocation for root components.
// JB: The root component relative location is redundant as it equals to the actor location.
// JB: Having it set during deserialization causes problems with PhysicX when a large number of prefabs are spawned at runtime.
// JB: Restoring the relative location will essentially put all spawned actors on top of each other even if the prefabs are spawned at different places.
// JB: In such a case, the physics has to deal with the overlaps (or at least I think so) and significantly slows down.
// JB: Especially if the assets have a large number of collisions.
USceneComponent* SceneComponent = Cast<USceneComponent>(ObjToSerialize);
if(SceneComponent && Cast<UPrefabComponent>(SceneComponent->GetAttachParent()))
{
if (Property->GetName().Equals("RelativeLocation"))
{
return true;
}
}


return false;
}

Expand Down Expand Up @@ -343,6 +359,7 @@ namespace {
}

UPrefabricatorAsset* PrefabAsset = Cast<UPrefabricatorAsset>(PrefabActor->PrefabComponent->PrefabAssetInterface.LoadSynchronous());
USceneComponent* SceneComponent = Cast<USceneComponent>(ObjToSerialize);

if (!PrefabAsset) {
return;
Expand Down Expand Up @@ -515,12 +532,28 @@ void FPrefabTools::LoadActorState(AActor* InActor, const FPrefabricatorActorData
for (const FPrefabricatorComponentData& ComponentData : InActorData.Components) {
if (UActorComponent** SearchResult = ComponentsByName.Find(ComponentData.ComponentName)) {
UActorComponent* Component = *SearchResult;
USceneComponent* SceneComponent = Cast<USceneComponent>(Component);

// JB: We store the world location in case we would be restoring a component simulating physics.
// JB: This is necessary only for prefab spawned at runtime.
FVector WorldLocation = FVector::ZeroVector;
if (InActor->HasActorBegunPlay()) {
if (SceneComponent)
{
WorldLocation = SceneComponent->GetComponentLocation();
}
}

bool bPreviouslyRegister;
{
//SCOPE_CYCLE_COUNTER(STAT_LoadStateFromPrefabAsset_UnregisterComponent);
bPreviouslyRegister = Component->IsRegistered();
if (InSettings.bUnregisterComponentsBeforeLoading && bPreviouslyRegister) {
Component->UnregisterComponent();
// JB: Some of the components (e.g., UPhysicsConstraintComponent) also require re-initialization.
if (Component->HasBeenInitialized()) {
Component->UninitializeComponent();
}
}
}

Expand All @@ -532,7 +565,14 @@ void FPrefabTools::LoadActorState(AActor* InActor, const FPrefabricatorActorData
{
//SCOPE_CYCLE_COUNTER(STAT_LoadStateFromPrefabAsset_RegisterComponent);
if (InSettings.bUnregisterComponentsBeforeLoading && bPreviouslyRegister) {
// JB: Register component will also initialize component if necessary.
Component->RegisterComponent();
// JB: Components that are simulating physics are detached from the actor on register.
// JB: Restoring their relative location above will cause them to be spawned at a wrong location so we fix it.
// JB: This is necessary only for prefab spawned at runtime.
if (InActor->HasActorBegunPlay() && SceneComponent->IsSimulatingPhysics()) {
SceneComponent->SetRelativeLocation(WorldLocation);
}
}
}
}
Expand Down Expand Up @@ -679,7 +719,9 @@ void FPrefabTools::LoadStateFromPrefabAsset(APrefabActor* PrefabActor, const FPr
}
}

ChildActor = Service->SpawnActor(ActorClass, FTransform::Identity, PrefabActor->GetLevel(), Template);
//JB: Spawning actors on top of each other may cause problems with PhysicX (as it needs to compute the overlaps).
FTransform WorldTransform = ActorItemData.RelativeTransform * PrefabActor->GetTransform();
ChildActor = Service->SpawnActor(ActorClass, WorldTransform, PrefabActor->GetLevel(), Template);
if (!Template) {
LoadActorState(ChildActor, ActorItemData, InSettings);
if (InState.IsValid()) {
Expand Down