How to Add a Scene Component in C++?

Hi - I’m trying to add a simple scene component (called HeldItemRoot) in C++ and attach it to my character mesh.

It looks fine in the editor when I compile and launch UE5 although the details panel is blank and it gets destroyed at launch when I hit play!?!?

I think I’m setting it up wrong? I’ve read others have had this issue historically but couldn’t find a good solution online. Any experts out there know the right way to get this working? Many thanks!

.h

public:
// Add Scene Component to hold item/weapon meshes
	UPROPERTY(BlueprintReadWrite, VisibleAnywhere)
	USceneComponent* HeldItemRoot;

.cpp

// Add Scene Component (Held Item Root) & attach to mesh
	HeldItemRoot = CreateDefaultSubobject<USceneComponent>(TEXT("HeldItemRoot"));
	HeldItemRoot->SetupAttachment(GetMesh());

how about recreating the blueprint pawn, it could be glitch.

1 Like

You mean build a whole new blueprint child from scratch? My blueprint child of my c++ class has tons of code in it and I have other children of that. That would be a massive undertaking for something like this. Or do you mean something more simple?

Recreate the blueprint class of the c++ class, try to see if it works or not. Such thing happened to me for several times.

By recreate you mean build a new blueprint class for the child of the c++ class that’s same same as my current blueprint class, correct?

This is how I would do it. Give it a shot. Code is untested:

auto newComponent = NewObject<USceneComponent>(this, USceneComponent::StaticClass());

if(newComponent)
{
    HeldItemRoot = newComponent;
	newComponent->AttachToComponent(GetMesh(), FAttachmentTransformRules::KeepRelativeTransform);
	newComponent->RegisterComponent();
	AddInstanceComponent(newComponent); // Refresh the editor so we can see the component
	newComponent->Activate();
}

This should create a SceneComponent connected to the mesh returned by GetMesh.

Thanks so much, will try this out later and confirm back.

No dice I’m afraid. Here’s the log error:

NewObject with empty name can’t be used to create default subobjects (inside of UObject derived class constructor) as it produces inconsistent object names. Use ObjectInitializer.CreateDefaultSubobject<> instead.

Hi, yeah an absolutely confounding thing about the engine is you have to use a different call to add or attach a component in constructor vs. at runtime. Kinda ridiculous that they couldn’t just hide all that behind the scenes. :expressionless:

If you add a scene component in constructor it is like this:

DefaultSceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("DefaultSceneRoot"));
	RootComponent = DefaultSceneRoot;

If you add a scene component in an actor any time outside construction, it is like this:

_zoneVisualizationMesh = NewObject<UStaticMeshComponent>(this, "VisualizationComponent");
1 Like

BTW, you can make a nice, clean “AddComponent()” function by detecting the thread context and using the appropriate way to instantiate. Kinda annoying that we have to do this … but not aware there is another way?

Code for detecting thread context. There’s a function for both because sometime it reads better either way.

bool UObjectUtilities::GetThreadContextIsContructor()
{
	FUObjectThreadContext& ThreadContext = FUObjectThreadContext::Get();
	if (ThreadContext.IsInConstructor > 0)
	{
		return true;
	}
	else
	{
		return false;
	}
}

bool UObjectUtilities::GetThreadContextIsRuntime()
{
	FUObjectThreadContext& ThreadContext = FUObjectThreadContext::Get();
	if (ThreadContext.IsInConstructor > 0)
	{
		return false; 
	}
	else
	{
		return true; 
	}
}
1 Like

I didn’t realize where you were calling the code because you didn’t show that in your problem statement. My code should work when being called outside of the constructor. Shmoopy’s code should work inside of a constructor.

Thanks Both. My original code is in the constructor and looks like what @Shmoopy1701 is recommending though, right?

What’s the alternative to doing it out of the constructor? I could try the other way, but does that mean doing it in Begin Play? (Sorry, I’m newer to C++).

Actually, I’ve solved it by using my original code but reparenting my blueprint class to the Character class and then reparenting it back to my custom C++ class.

This seems like a bug for that to be the solution!?!?

Yes, it’s a known bug with the hot reload system. When changing something in a header file or constructor for an already blueprinted class, you should close the editor before compiling. Otherwise, you’ll need to do what you did and reparent your blueprint and then re-reparent it back.

This is great to know, thank you. And thanks to everyone that tried to help me here. Appreciate you all!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.