I’m implementing a preview of a spawner component.
AttachToComponent returns True, and preview actor Attaches as a child on the world outliner, but stays in place when the parent Actor is moved.
I think that something is needed more to do this at the editor level, but I’m not sure.
Also, the code to delete it when the ActorClass changes is not triggered because the PreviewActor is always nullptr. I don’t know why this is.
// .h
UPROPERTY(VisibleAnywhere, Category = "Spawner")
TWeakObjectPtr<class ASpawnerPreviewActor> PreviewActor;
// .cpp
void USpawnerComponent::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent)
{
Super::PostEditChangeProperty(PropertyChangedEvent);
const FName PropertyName = PropertyChangedEvent.GetPropertyName();
if (PropertyName == GET_MEMBER_NAME_CHECKED(USpawnerComponent, ActorClass))
{
InitPreview();
}
}
void USpawnerComponent::InitPreview()
{
if (PreviewActor.IsValid())
{
PreviewActor->Destroy();
PreviewActor.Reset;
}
...
FActorSpawnParameters Params;
Params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
if (ASpawnerPreviewActor* NewActor = World->SpawnActor<ASpawnerPreviewActor>(Params))
{
USceneComponent* PreviewRootComp = NewActor->GetRootComponent();
// Register Root Component
PreviewRootComp->RegisterComponent();
NewActor->AttachToComponent(this, FAttachmentTransformRules::SnapToTargetIncludingScale);
NewActor->OwnerSpawner = this;
// Temp Actor for duplication
AActor* TempActor = World->SpawnActor<AActor>(ActorClass);
TempActor->RegisterAllComponents();
// PrimitiveComponent Refs
TArray<UPrimitiveComponent*> PrimitiveComps;
TempActor->GetComponents(UPrimitiveComponent::StaticClass(), PrimitiveComps);
// Duplication and register component
for (UPrimitiveComponent* const& PrimitiveComp : PrimitiveComps)
{
UPrimitiveComponent* NewComp = DuplicateObject<UPrimitiveComponent>(PrimitiveComp, NewActor);
NewActor->AddInstanceComponent(NewComp);
NewActor->AddOwnedComponent(NewComp);
NewComp->RegisterComponent();
bool bSuccess = NewComp->AttachToComponent(PreviewRootComp, FAttachmentTransformRules::SnapToTargetIncludingScale);
UE_LOG(FCSpawner, Warning, TEXT("AttachToComponent %s"), bSuccess ? TEXT("Succeed") : TEXT("failed"));
NewComp->SetRelativeLocationAndRotation(PrimitiveComp->GetRelativeLocation(), PrimitiveComp->GetRelativeRotation());
}
// Destroy Temp Actor
TempActor->Destroy();
PreviewActor = NewActor;
}
}