I have a collection with Instanced and EditinlineNew objects.
UPROPERTY(EditAnywhere, BlueprintReadOnly, Instanced, meta = (AllowPrivateAccess = "true"), Category = "Prioritized Actions")
TMap<FName, TObjectPtr<URDBasePrioritizedAction>> PrioritizedActions;
/**
* Base class for any prioritized action.
*/
UCLASS(Abstract, BlueprintType, Blueprintable, DefaultToInstanced, EditInlineNew, Within = RDBasePrioritizedActionManagerComponent)
class URDBasePrioritizedAction : public UObject
{
GENERATED_BODY()
};
I can then add instances of these objects and edit them in the blueprint which is nice.
However when I try to prepopulate the map with some objects from C++ I have some odd results. The edits that I make to the objects that were prepopulated from C++ are actually not reflected. So in my Drop State Name, I set it to None, but the value stays at the original value and my code doesn’t work.
I thought it’d be nice to prepopulate the map with some important default objects while the rest are editable with blueprint.
ASFInventoryEquippable::ASFInventoryEquippable(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
StateMachineComponent = CreateDefaultSubobject<URDBaseStateMachineComponent>(TEXT("StateMachineComponent"));
StateMachineComponent->OnCurrentStateGameplayTagsChanged.AddDynamic(this, &ASFInventoryEquippable::OnCurrentStateGameplayTagsChanged);
ActionManagerComponent = CreateDefaultSubobject<URDBasePrioritizedActionManagerComponent>(TEXT("ActionManagerComponent"));
// Add the built in actions for idle, unequip, and drop
if (ActionManagerComponent)
{
ActionManagerComponent->CreateDefaultSubobjectPrioritizedAction<USFEqAction_Idle>(TEXT("IdleAction"), TEXT("Idle"));
ActionManagerComponent->CreateDefaultSubobjectPrioritizedAction<USFEqAction_Unequip>(TEXT("UnequipAction"), TEXT("Unequip"));
ActionManagerComponent->CreateDefaultSubobjectPrioritizedAction<USFEqAction_Drop>(TEXT("DropAction"), TEXT("Drop"));
}
}
URDBasePrioritizedAction* URDBasePrioritizedActionManagerComponent::CreateDefaultSubobjectPrioritizedAction(FName SubobjectName, FName ActionName,
TSubclassOf<URDBasePrioritizedAction> ActionClass, bool bTransient)
{
if (!ActionClass)
{
return nullptr;
}
UE_CLOG(PrioritizedActions.Find(ActionName), RDBase, Fatal, TEXT("Action name \"%s\" already exists in action manager."), *ActionName.ToString());
UE_CLOG(ActionName == NAME_None, RDBase, Fatal, TEXT("Can't have actions with name NONE"));
FObjectInitializer* CurrentInitializer = FUObjectThreadContext::Get().TopInitializer();
UE_CLOG(!CurrentInitializer, RDBase, Fatal, TEXT("No object initializer found during construction."));
URDBasePrioritizedAction* Action = Cast<URDBasePrioritizedAction>(CurrentInitializer->CreateDefaultSubobject(this, SubobjectName, ActionClass, ActionClass, true, bTransient));
PrioritizedActions.Add(ActionName, Action);
return Action;
}
It seems like the create default sub object method is the only thing that currently works, when I don’t try to create these as default subobjects from the constructor, they turn null. If I create them from BeginPlay they won’t show up at all in the blueprint editor since they’re created at runtime in game later, then I can’t edit them at all.
Maybe it’s something to do with the objects being stuck as they are in the C++ class and there’s no way to edit their instances in the blueprint editor?