The class inherits ACharacter.
Already tried using Initializer with Super and FObjectInitializer, but still creates these unwanted default duplicates. Fighting with this for over a day!
Doing it the way you did it in your first post is the right way, your logging in that first post makes little sense though because you’re checking the validity of pointers that will never be set. Initialization code will use the classes you provided and store those components in the same variables as it usually would (ACharacter::Mesh, ACharacter::Capsule, ACharacter::CharacterMovement).
There MIGHT be a bug with existing blueprint classes and changing the components like this, so to make sure the first step works I’d create a new blueprint class if I were you. If that works, and your existing blueprint doesn’t, either migrate the rest of the BP logic or try to figure out why it doesn’t work (maybe reparenting fixes it?).
Your second approach will ofc still create the default components and, while you COULD destroy them and reassign the pointers to your components instead, I would recommend against it because the first approach is the intended one.
Could you try using MeshComponentName, CharacterMovementComponentName, and CapsuleComponentName (they’re all members of ACharacter) for your SetDefaultSubobjectClass names and see if that changes anything? The default components might not override properly if you’re not using matching names.
And added these to BPF_Init_SetupComponents(), but now cause the engine to crash, now that I did the deep clean (removed and regenerated binaries and etc).
I actually have, on released projects, and I’m currently working on a AAA project where we’re doing this for basically all base classes.
It’s a bit hard to debug this with partial context and no access to a debugger though, so it would help a lot if you tried using the built-in component names.
Also, you don’t have to believe me, you can give the engine sources a look yourself and you’ll see UE does this with its own classes. Also, this is literally the comment next to one of those names: /** Name of the CharacterMovement component. Use this name if you want to use a different class (with ObjectInitializer.SetDefaultSubobjectClass). */
Couldn’t get rid of rest because they were tagged as “required”.
I also looked into Output Log, and I think I found where the problem is.
LogUObjectGlobals: Error: Class /Script/Conduit.CndComp_Character_Capsule is not a legal override for component None because it does not derive from Class /Script/Conduit.CndComp_Character_Mesh. Will use Class /Script/Conduit.CndComp_Character_Mesh when constructing component.
LogUObjectGlobals: Error: Class /Script/Conduit.CndComp_Character_Mesh is not a legal override for component None because it does not derive from Class /Script/Conduit.CndComp_Character_Move. Will use Class /Script/Conduit.CndComp_Character_Move when constructing component.
CndCharacter_Master.h has CndComp_Character.h included.
The custom FNames you’re using seem to not be initialized at the point those error messages were outputted, so you’re essentially providing a bunch of overrides for the “None” component. The errors turn out a bit unclear because engine code doesn’t ensure the provided overrides are unique, just packs them in an array and processes them later.
To verify, you can add logging to the constructor, your FNames should all print None.
To repeat myself, even if you fix this (by ensuring the names are initialized), you’re still fighting against the engine for no reason and (as you’ve seen) some components you won’t easily be able to remove. Using the built-in names for overrides would fix all of this; and if there is an issue with that, we can debug that issue.