Add components dynamically

Hi everyone,

I am trying to create actors dynamically, and add to them components. But for now, it just crashes when I add a new component on my new actor…

Here is my code :

void AContentReader::CreateActor(const s_Content &data)
{
	if (GEngine)
		GEngine->AddOnScreenDebugMessage(-1, 2, FColor::Yellow, "Creating actor");
	FTransform tr = ConvertMatrixToTransform(data.matrix);
	_actor = GetWorld()->SpawnActor<AActor>(tr.GetLocation(), FRotator(tr.GetRotation()));
	if (!_actor)
	{
		if (GEngine)
			GEngine->AddOnScreenDebugMessage(-1, 2, FColor::Red, "Actor creation failed");
		return;
	}
	_parent = _actor->CreateDefaultSubobject<USceneComponent>(TEXT("Root")); //  <-- This line makes crash
	return;
	_actor->SetRootComponent(_parent); //Not used for now
}

I have my new AActor, that’s fine, but it crashes when I use CreateDefaultSubobject.

I don’t really get what is happening. I am using CreateDefaultSubobject in another class in this project, and it works perfectly.

Should I call this function only in a constructor ? For now, my CreateActor function is call once, in a Tick. Is that the issue ?

Hi,

Im useing this to spawn dynamic spline mesh components:

USplineMeshComponent* SplineMeshComp = ConstructObject<USplineMeshComponent>(USplineMeshComponent::StaticClass(), this);

I cant tell you why this should work and yours doesnt, but i can remember that i had problems with that, too.

Hope that helps…

Hi ,

Thanks for the answer ! Unfortunatelly, for me, it does’nt solve my problem, I still have the crash :confused:
I am wondering what I did wrong…

You can only use CreateDefaultSubobject in the constructor. Why not just use SpawnActor and create the necessary components in the constructor of your actor?

Hello,

could you be more specific about what type of crash happens and where it breaks? (LIke which breakpoint hits/ in what method)

You could try to give it another name. “Root” might give you a crash …

Good luck with that! :slight_smile:

Ok thanks, that’s what I expected… I can’t create my components on the constructor of an object, cause I will add components through the game :confused:

Any idea of how I could do that ? (if it’s possible…)

Hello,

The crash occurs in this line :

_parent = _actor->CreateDefaultSubobject(TEXT(“Root”));

The editor just freeze, and then the memory increase until it reach 100% of memory taken, or until I kill it ^^

I will not be able to change my code before friday, but i will test to change the name

Ohhh and I didn’t read your code carefully enough!

You should use this:

USceneComponent* createdComp = ConstructObject<USceneComponent>(YourComponentsActualClass, this, YourComponentsAddedName);
if(createdComp)
{
	createdComp->RegisterComponent();
	createdComp->AttachTo(GetRootComponent(), NAME_None);
}

This also returns a reference to the newly constructed component :slight_smile:

EDIT: I use this exact code and it works nicely :slight_smile:

I have already tried that but it didn’t work :confused:

I will test another time because maybe I missed something !

I will tell you on Friday.

Thanks for you answer :slight_smile:

Did you use RegisterComponent()? Yeah just try it and let me know, if there are any problems using that code :slight_smile:

I didn’t so it may come from that ! :slight_smile:

It works perfectly ! :slight_smile:
Thanks a lot !

I’m seeing a lot of relevant answers but I want to point out that ConstructObject is deprecated (as of 4.8?!?), with a note saying to use NewObject instead.

You should use NewObject instead.
such as

NewObject< UStaticMeshComponent>(this);

Tutorial on Dynamical Constraint Creation

I added this as a follow up answer for future readers.

… here is my solution :

UE_LOG(LogTemp, Warning, TEXT(" ---- spawning ---- "));
AUnitElement* sample = GetWorld()->SpawnActor<AUnitElement>(AUnitElement::StaticClass(), FVector::ZeroVector, FRotator::ZeroRotator);
(sample->GetRootComponent())->AttachToComponent(ElementBox, FAttachmentTransformRules::SnapToTargetNotIncludingScale);
FVector temp = UKismetMathLibrary::RandomPointInBoundingBox(ElementBox->Bounds.Origin, ElementBox->Bounds.BoxExtent);
sample->SetActorLocation(temp);

AUnitElement* is your “other” actor which has mesh inside.

ElementBox is just a container of UBoxComponet inside my class and is attached to the root

ElementBox = CreateDefaultSubobject<UBoxComponent>("Element Box");
RootComponent = ElementBox;

temp is a location vector made based on size of ElementBox .