What is the proper way to set up an APawn subclass for blueprintability?

I’m trying to create an APawn subclass in C++, because I’m going to do more math than would be comfortable in blueprint.

I’d like this Pawn to have a hierarchy of static mesh components: Body -> Femur -> Tibia -> Metatarsal.
(Actually, there are more Femurs, etc; one chain per leg.)

I do NOT want to do this as a skinned mesh; I want to define a separate mesh for each.

Now, I’ve set up the APawn with a number of properties:



UPROPERTY(EditAnywhere, BlueprintReadWrite)
UStaticMeshComponent *Root;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
UStaticMeshComponent *Body;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
UStaticMeshComponent *FrontLeftFemur;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
UStaticMeshComponent *FrontLeftTibia;
....


I then create the Root and the different components as follows:



(inside the constructor, taking an FObjectInitializer):

	Root = OI.CreateAbstractDefaultSubobject<UStaticMeshComponent>(this, TEXT("Root"));
	RootComponent = Root;	//	for AActor
	Root->SetupAttachment(nullptr, TEXT("Root"));
	Body = NewObject<UStaticMeshComponent>(this, L"Body");
	Body->AttachToComponent(Root, FAttachmentTransformRules::KeepRelativeTransform, L"Body");
	Body->RegisterComponent();
	FrontLeftFemur = MakeLegBone(BodyMesh, L"FrontLeftFemur");
	FrontLeftTibia = MakeLegBone(LegLeftUpper, L"FrontLeftTibia");
        .....


The MakeLegBone function does this:



UStaticMeshComponent *AStompyRobotPawn::MakeLegBone(UStaticMeshComponent *Parent, FName const &Name)
{
	UStaticMeshComponent *ret = NewObject<UStaticMeshComponent>(this, Name);
	ret->AttachToComponent(Parent, FAttachmentTransformRules::KeepRelativeTransform, FName(Name));
	ret->RegisterComponent();
	ret->bCreatedByConstructionScript_DEPRECATED = true;
	ret->bAllowAnyoneToDestroyMe = true;
	return ret;
}


I can create a blueprint subclass of this object, call it BP_Pawn, and then open it up.
First, it doesn’t open with a Viewport, so I have to click the “open full blueprint editor” to get there.
Second, when I try to save, I get the error:

I think I’m perhaps on the right way, but there are specifics about how to create these components to make them show up properly in the blueprint editor, and then be able to save them.
What am I missing here? I’ve read the documentation for the APawn and UStaticMeshComponent classes, but they aren’t particularly helpful with the “why” of the outer surroundings.
What’s a good link for the surrounding environment knowledge I need to have to move forward with this?

Use CreateDefaultSubobject<>() instead of NewObject<>()

This. Working fine for me with DefaultSubobject.

also:


	Root->SetupAttachment(nullptr, TEXT("Root"));

why?

You should also mark you component properties as (VisibleAnywhere, BlueprintReadOnly), plus add a category specifier.
With subobjects, editable means you can actually recreate the subobject from a blueprint rather than just edit it’s properties, which I don’t think is what you intend and has some limitations and side effects regarding how they show up.

Why? What is the different between CreateDefaultSubobject<> and NewObject<> ?
What about NewObject<> would cause the problems with the chain reference?

Why not?
It looks like each component needs to be attached to something, and I’d like it to be attached to the actor itself.
What’s mistaken about this assumption?

OK, I’ll try that. Thanks! The description “has some side effects” is somewhat helpful, and more precision (or, ideally, a pointer to the documentation that actually specifies these side effects) would be great!

Do I need to RegisterComponent the root component? The documentation just says “adds to outer Actor’s Components array” but doesn’t tell me what happens if it’s not there, or whether some components are auto-registered.

Yes, but “nullptr” doesn’t mean you’re attaching it to the actor - you’re just trying to attach it to something nonexistent.
I’m not sure, but the first created subobject will be setup as the rootcomponent by default - if you don’t attach it to something else or the default root scene component.
(RootComponent = Root;)


Root->SetupAttachment(nullptr, TEXT("Root"));

So that’s pretty much useless code and would crash - if there wouldn’t be an exception handler for a nullptr inside SetupAttachment().

It’s just one of UE4’s many rules, never call NewObject from within a UObject class constructor. In a constructor, you’re creating a default subobject (something that should exist for every instance of that class) and that needs the special handling provided by CreateDefaultSubobject.

As for the EditAnywhere side effects, you should be able to see the difference if you try it. Properties get displayed in a non-standard way, all categories collapsed by default. Also it may not play nice with the component list in Blueprints, I don’t remember exactly. Documentation link? That’s optimistic :wink:

And as for registering, pretty certain there’s no need to manually register any component if it’s created as a subobject in the constructor, they should all get auto-registered.

Alright, that gives me something to go on. Thanks all!
(And, in fact, it does work as I expect when I use CreateDefaultSubobject<>())

“You should never use NewObject in object construction” is a fine rule, I guess, I just would like to know where I can read up on this rule (and others like it) without having to post in forums for each function I’m trying to use …