I have a C++
ACharacter subclass called
AClassBase, and it has a component
UPROPERTY(EditDefaultsOnly) class UWeapon * Weapon;
I want to derive multiple versions of
AClassBase in Blueprint, but replace the
Weapon – e.g. a
Rogue that has an
UKnife for its
UKnife would be inheriting from
UWeapon. Ideally I would be able to do this just in the Class Defaults for the subclass.
I can’t seem to figure out how to do it – when I am editing the derived Blueprint class, it just says “Cannot edit variable type when they are inherited from parent.” for the type of
Weapon. I’ve tried using
Weapon = CreateAbstractDefaultSubobject(TEXT("Weapon")); in
Previous questions found in my searches that did not answer my question:
https://answers.unrealengine.com/questions/46003/how-to-let-subclasses-override-components.html – which didn’t have an answer in May '14. There’s also
https://answers.unrealengine.com/questions/54499/override-on-blueprint-components.html – which only has an answer that uses a construction script (which I’d like to avoid) and replaces variables in the component, not the type of the component.
https://answers.unrealengine.com/questions/44855/how-to-let-super-classes-override-components.html – this seems to be C++ only, and to be referencing APIs that no longer exist.
Alternatively, it could also work if I had a
TWeakObjectPtr in the parent that I could point to a real component on the derived class. I haven’t been able to figure out how to do this in the Class Defaults for the subclass, and if I use a Construction Script, it seems like it is executed after the
AClassBase::PostInitProperties() – not sure when the construction script is actually run.
Thank you for your time.
The abstract subobject method will work, but only in C++. You’d need a derived C++ class for each character type (which you could then further specialize in a blueprint if you wanted). To do that, declare your base class constructor with an
AClassBase::AClassBase(FObjectInitializer const& OI)
Weapon = CreateAbstractDefaultSubobject< UWeapon >(TEXT("Weapon"));
Then in each of your derived classes, you need to override as follows:
ADerived::ADerived(FObjectInitializer const& OI): Super(OI.SetDefaultSubobjectClass< UKnife >(TEXT("Weapon")))
Your alternative approach is also an option, it has the advantage that you can add new subclasses and select their weapon type purely in blueprint, with the disadvantage that it requires a bit more manual setup. Basically, you’d just create whatever component you want via the
AddComponent button in the blueprint editor for each blueprint subclass you have, and assign it to your pointer property at some point so the base class can access it.
BeginPlay would be the safest place to do it. If your base class needs access to it earlier than
BeginPlay, then I would have thought the construction script would work - it’s run every time you change any property of an actor in the editor.
Frustrating that it still is not possible to change the type of the component from the class defaults. That would have been great for avoiding Blueprint code dependencies.
I think I will end up using
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) TSubclassOf(UWeapon) WeaponType; and then have a
UPROPERTY(VisibleInstanceOnly, BlueprintReadWrite) class UWeapon *Weapon;. Then
AClassBase::BeginPlay() can spawn the WeaponType and assign it to the Weapon instance. It means I can’t do configuration of class defaults for e.g. UKnife (like setting the damage or other effects), but I can get around that by just creating a Blueprint Class for the specific UKnife settings I want and configuring it there, then assigning that Blueprint Class to WeaponType.
Thank you for your answer!
Yep, that’s a common approach but like you say suffers from the fact that you can’t edit component properties inline, or per instance.
I believe I read ages ago that providing the
SetDefaultSubobjectClass functionality in blueprints was something Epic wanted to do, but it hasn’t happened and suspect it probably won’t anytime soon.