Hello, I’m trying to set up a reusable hierarchy of components, I mean by that a component that will instantiate and attach to itself other component
The goal is to factorize code, in my precise case for everything related to the arms of a character, have an arm mesh, a motion controller, and other custom components packed into one “arm” component so I can manage right and left arm without code duplication
To simplify things let’s say I have one character c++ class, that is inherited by a blueprint. In this class I instantiate a custom scene component, and this custom scene component will instantiate a mesh component and attach it to itself.
The problem is when I open the character blueprint, I don’t have anything in the details tab for the mesh component. Some of its properties are available through the details tab of its parent scene component, but not at the same level of detail that I would get by instantiating the mesh directly from the character.
Is there a way to access this details ? Is it a bug of the editor ? Is my approach correct ? maybe the way I instantiate the child mesh component is not the best way ?
Thank you in advance for you help !
class TESTCOMPONENTS_API AMyCharacter : public ACharacter
// Sets default values for this character's properties
// Sets default values
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
MySceneComponentInstance = CreateDefaultSubobject<UMySceneComponent>(TEXT("MySceneComponent"));
MySkeletalMeshComponent = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("MySkeletalMeshComponent"));
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class TESTCOMPONENTS_API UMySceneComponent : public USceneComponent
// Sets default values for this component's properties
// Sets default values for this component's properties
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
PrimaryComponentTick.bCanEverTick = true;
bEditableWhenInherited = true;
MySubSkeletalMeshComponent = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("MySubSkeletalMeshComponent"));
MySubSkeletalMeshComponent->bEditableWhenInherited = true;
The resulting views in the editor for the character blueprint, taking the Collision Category as an example :
I’ve tried all these before posting, but it doesn’t solve my problem.
The difference relies only in the fact that in one case the mesh component is declared and created in the character derived class, and in the other case it is done in the component derived class
My next try was to use the ObjectInitializer from the character constructor and pass it down to the component so the sub component is created in the name of the character class, but that did not solve the problem
Following the code, the 2 mesh components should be created exactly in the same way, but I guess the fact that the property is declared in the component is the key
I’ve tried to find a meta parameter for the property that would solve the problem, but without any luck
another thing I discovered and should be carefully taken care of, is that if you change your C++ properties after you have created a derived blueprint, properties can be messed up with because the blueprint will serialize them and can mix things up when loading the BP and deserialize the BP parameters after your changes.
Typically sub components will be set to null, but I have also seen two components of the same type have their parameters exchanged ! The solution for this is to declare the property with the specifier SkipSerialization
It seems nobody seems to know quite how to resolve this specific problem, and/or nobody gets the same repro as we do. I find it somewhat comforting to know I’m not alone, but it sucks that in all this time there doesn’t seem to have been a solution for this.
None of the solutions work for me: BlueprintReadOnly/ReadWrite, Visible/EditAnywhere, Category setting, public/protected/private, using the FObjectInitializer for the Constructor, reparenting, redefining, renaming, recompiling, recreating the derived Blueprint, adding an Instance Component instead. Nothing.
I’ve been researching the issue for a couple of hours again just now, and I’m very close to just creating the components I need through Blueprint and trying to write whatever functionality I want in C++, although I’m pretty sure that’s not actually a good idea. Just exploring new avenues as this one seems a dead end for me, at the current time.
Good luck! If you ever do find a solution, please contact me ASAP.
True – in my tests I keep recreating the Blueprint to get a “fresh start” and initialise the starting conditions of my problem. I spotted a sneaky “MySubSkeletalMeshComponent->bEditableWhenInherited = true;” in your post that I hadn’t caught before. My last hope for my own problem…!
Unfortunately, no dice. They’re not showing up, neither in their own Details panels, nor in those of their parents (everything is empty).
I do have a work-around in mind though: I can expose regular variables to the Details panel of the main Blueprint itself, for example Material asset selectors. Perhaps I’ll use this area to set the Mesh and other parameters I care about for my C+±created components, and simply hope that, one day, this bug will finally be squashed.
#define MAKE_SUBCOMPONENT_NAME(ParentName, SubObjectName) FName(*FString::Printf(TEXT("%s_%s"), *ParentName, TEXT(SubObjectName)))
UArmComponent::UArmComponent(const FObjectInitializer& ObjectInitializer)
// arm 1st person mesh
FString ArmName = GetName();
ArmSkeletalMesh = ObjectInitializer.CreateDefaultSubobject<USkeletalMeshComponent>(this, MAKE_SUBCOMPONENT_NAME(ArmName, "ArmSkeletalMesh"), true);
ArmSkeletalMesh->bEditableWhenInherited = true;
// parameters that used to be set in the blueprint
// but they have no reason to be changed
ArmSkeletalMesh->bOnlyOwnerSee = true;
ArmSkeletalMesh->CastShadow = false;
ArmSkeletalMesh->bCastDynamicShadow = false;
ArmSkeletalMesh->bAffectDynamicIndirectLighting = false;
ArmSkeletalMesh->bAffectDistanceFieldLighting = false;
ArmSkeletalMesh->bCastStaticShadow = false;
// apply the transform that was set in the blueprint