Download

BP default value, C++ constructor

BP default value is not being passed to the C++ constructor. I want to spawn by ObjectInitializer.CreateDefaultSubobject in the blueprint editor from an array, but it seems that c++ constructor fires first before the BP default is read, so there’s nothing being spawned in the editor.

So is there a way to pass BP default value before C++ contructor fires, like a deffered spawn.

My fix right now is using the BP constructor, but pawning objects there doesn’t reference it to the BP default, so I can’t really edit the value of those spawned object, this is only good for passing value like a float to the constructor. Unlike the one spawned by ObjectInitializer.CreateDefaultSubobject I can edit their values but as the first problem goes I can’t dynamically spawn object from an array.

You are misunderstanding how the engine works;
Your Blueprint is not your C++ class. Therefore you shouldn’t expect your C++ object to interact with a Blueprint’s (fake) constructor. The BP constructor function was created to emulate the C++ CDO behaviour, but it is not really an object constructor.

So, it’s not possible to send info from BP default to C++ Constructor?

What do you mean with BP default?

It is possible to gather information in your Blueprint and using PostInit for example to get the data you want and use it back in your C++ class again. If that’s what you want, I advise you reading https://docs.unrealengine.com/latest/INT/Programming/Introduction/index.html

I know it’s labeled introduction, but it shows the communication between C++ and Blueprints. If this communication between C++ and Blueprints is not your problem, please go ahead and give more details, so we can help <3.

1 Like

You can’t control default subobject creation from BP, no. No blueprint properties even exist at the time the C++ constructor is run.

@Ninjin BP default as in the UPROPERTY. Thanks, what I needed was the PostEditChangeProperty. Though there’s another problem, the value edited in the BP default is not being passed to runtime

Yeah, but how does the +AddComponent in the BP work though?

With a great deal of extra supporting code. I’m not saying it’s not feasible in theory - pretty sure I recall someone from Epic saying it was on the wanted list years ago. But currently the engine doesn’t let you do this in response to values in blueprint properties.

It’s not quite the same thing anyway - ‘Add Component’ is essentially changing the structure of the blueprint class itself; what you’re after would require changing the structure of the class in response to changes to the value of a property in the CDO instance of that class.

I got it working, I can now add object though BP default array in the editor.

Also, the value is now passed to runtime, maybe it’s because of the Transient tag, I haven’t checked.

This solved many of my problem lol.

Can you show us how you solved this with some code please?

/////////////////////ItemBase.h

#include “CoreMinimal.h”
#include “GameFramework/Actor.h”
#include “Engine/StaticMesh.h”
#include “Engine/DataTable.h”
#include “ItemBase.generated.h”

USTRUCT(BlueprintType)
struct FItemBaseStruct : public FTableRowBase
{
GENERATED_BODY()

UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Base")
float MaxCombine;

UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Base")
bool bCombineAble;

UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Base")
UStaticMesh* ItemMesh;

};

UCLASS()
class THEMARS_API AItemBase : public AActor
{
GENERATED_BODY()

public:
// Sets default values for this actor’s properties
AItemBase();

protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;

public:
// Called every frame
virtual void Tick(float DeltaTime) override;

FORCEINLINE const FItemBaseStruct& GetItemBaseStruct() const { return ItemStruct; }

void PostInitProperties() override;
void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;

private:
UPROPERTY(VisibleAnyWhere, BlueprintReadOnly, meta = (AllowPrivateAccess = “true”))
UStaticMeshComponent* ItemMesh;

UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Item", meta = (AllowPrivateAccess = "true"))
FItemBaseStruct ItemStruct;

};

////ItemBase.cpp

#include “ItemBase.h”

// Sets default values
AItemBase::AItemBase()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don’t need it.
PrimaryActorTick.bCanEverTick = true;

ItemMesh = CreateDefaultSubobject&lt;UStaticMeshComponent&gt;(TEXT("ItemMesh"));
RootComponent = ItemMesh;    

}

// Called when the game starts or when spawned
void AItemBase::BeginPlay()
{
Super::BeginPlay();

}

// Called every frame
void AItemBase::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);

}

void AItemBase::PostInitProperties()
{
Super::PostInitProperties();

if (ItemStruct.ItemMesh)
{
    ItemMesh-&gt;SetStaticMesh(ItemStruct.ItemMesh);
}

}

#if WITH_EDITOR
void AItemBase::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
if (ItemStruct.ItemMesh)
{
ItemMesh->SetStaticMesh(ItemStruct.ItemMesh);
}
Super::PostEditChangeProperty(PropertyChangedEvent);
}
#endif