I’m trying to create a custom component based on [this tutorial video][1] in order to facilitate level design. I basically want to be able to add it to a class and have it clone all scene components that are children of the root, offsetting them until an endpoint is hit.
To go from this:
https://forums.unrealengine.com/attachment.php?attachmentid=26271&d=1424419462
to this:
https://forums.unrealengine.com/attachment.php?attachmentid=26272&d=1424419528
and duplicate any meshes, shapes, etc.
It seems to work well enough in the Blueprint Component window, but when I place it in the scene and play in editor, all the added components disappear.
Stopped:
https://forums.unrealengine.com/attachment.php?attachmentid=26273&d=1424419797
Playing:
https://forums.unrealengine.com/attachment.php?attachmentid=26274&d=1424419817
This seems to clear up when I save the blueprint, or sometimes for seemingly no reason, and comes back when I change any properties of the wall.
More importantly, any added collision boxes disappear on play:
Stopped:
https://forums.unrealengine.com/attachment.php?attachmentid=26275&d=1424420115
Playing:
https://forums.unrealengine.com/attachment.php?attachmentid=26276&d=1424420126
which I can’t find any way to fix.
Here’s the code for the component:
void UProceduralWallComponent::GenerateWall(FVector Endpoint)
{
//Super::OnComponentCreated();
AActor* owner = GetOwner();
USceneComponent* root = NULL;
if (owner)
root = owner->GetRootComponent();
if (!root)
return;
if (root->GetNumChildrenComponents() < 1)
return;
USceneComponent* child = root->GetChildComponent(0);
float wallLength = Endpoint.Size();
float width = child->Bounds.BoxExtent.Y*2/child->GetComponentScale().Y;
FVector currentPoint = child->RelativeLocation;
currentPoint.Y += width;
TArray<USceneComponent*> clones;
//clone first child of the root
for (int i = 0; currentPoint.Y < wallLength; currentPoint.Y += width, ++i)
{
USceneComponent* currentComp = CloneComponent(child->GetClass(), child->GetName() + FString::FromInt(i), child, root);
if (!currentComp)
return;
currentComp->SetRelativeLocation(currentPoint);
clones.Add(currentComp);
}
//clone all children of the first child recursively
CloneRecursive(child, clones);
}
void UProceduralWallComponent::CloneRecursive(USceneComponent* parent, TArray<USceneComponent*> &parentClones)
{
TArray<USceneComponent*> children;
parent->GetChildrenComponents(false, children);
if (children.Num() == 0)
return;
for (USceneComponent* child : children)
{
int i = 0;
TArray<USceneComponent*> childClones;
for (USceneComponent* parentClone : parentClones)
{
USceneComponent* clone = CloneComponent(child->GetClass(), child->GetName() + FString::FromInt(i), child, parentClone);
childClones.Add(clone);
if (GEngine)
GEngine->AddOnScreenDebugMessage(-1, 1.f, FColor::Yellow, clone->GetName());
++i;
}
CloneRecursive(child, childClones);
}
}
USceneComponent* UProceduralWallComponent::CloneComponent(TSubclassOf<USceneComponent> CompClass, FString CompName, UObject* Template, USceneComponent* parent)
{
FName name(*CompName);
USceneComponent* newComp = ConstructObject<USceneComponent>(CompClass, GetOwner(), name, RF_NoFlags, Template);
if (GEngine)
GEngine->AddOnScreenDebugMessage(-1, 1.f, FColor::Yellow, newComp->GetClass()->GetName());
if (!newComp)
return NULL;
newComp->bCreatedByConstructionScript = true;
newComp->OnComponentCreated();
newComp->RegisterComponent();
if (newComp->bWantsInitializeComponent)
newComp->InitializeComponent();
if (parent->GetOwner())
parent->GetOwner()->AddOwnedComponent(newComp);
newComp->AttachTo(parent);
return newComp;
}
and the Blueprint calling it: