Download

UStaticMeshComponent::SetMaterial() working in BeginPlay() but not in constructor?

Hey there. I have this program below:
Why is it so that UStaticMeshComponent::SetMaterial() is not working in the constructor but in the BeginPlay() ?
It is a blueprint where i set the static mesh and material, that derives from the c++ class below.
If anybody have some input on this one I would be really greatful. Im new to c++/ue4 in general btw.



//MyActor.cpp


#include "objtest.h"
#include "MyActor.h"

AMyActor::AMyActor() {
EdgeMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Root"));
//This does not work it seems
EdgeMeshComponent->SetMaterial(0, Material);
RootComponent = EdgeMeshComponent;
}

void AMyActor::BeginPlay()
{
	Super::BeginPlay();
//This works it seems
	EdgeMeshComponent->SetMaterial(0, Material);
}
void AMyActor::Tick( float DeltaTime )
{
	Super::Tick( DeltaTime );
}





//MyActor.h


#pragma once

#include "GameFramework/Actor.h"
#include "MyActor.generated.h"

UCLASS()
class OBJTEST_API AMyActor : public AActor
{
	GENERATED_BODY()
public:	
	AMyActor();
	virtual void BeginPlay() override;
	virtual void Tick( float DeltaSeconds ) override;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "C++")
		UStaticMeshComponent* EdgeMeshComponent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "C++")
		UMaterialInterface* Material;

};




I am going to give my noob comment. Take it with lots of salt.

Constructor in c++ starts when you place the actor on to the level in editor. But if you need to place the actor on the level in editor then select to assign the material, constructor would not trigger again to assign the material. There are couple of ways you could try to get it to work.

  1. Hardcode the material to be assigned in the constructor instead of uproperty.

  2. Code setmaterial in OnConstruction function, where changes to the uproperty in the editor will be effected through the function. Only uproperty or ufunction values will be effected in this function (means the value will be brought over to begin play, other non “uproperty/ufunction” values will be reset to original values).

of course, because in the constructor the material is nullptr, then you set whatever value in the editor, thats way only work in begin play, you might integrate OnConstruction like @pickersZ said

You can use PostInitializeComponents() instead of BeginPlay() if you want, which will still be called when an object is ‘Constructed’ (well, kind of) - but at that point all the defaults values (e.g, what static mesh to use) you have set will be initialized.

I prefer to use PostInitComps instead of BeginPlay because I always know when it’s going to be called.

Ty for responses.
This may be a dumb question. Why is material nullptr but not staticmesh if both are linked/referenced in the blueprint child of the c++ class?

Edit:

Thx alot for help and input. Have looked a bit more into actor lifecycle/PostInitializeComponents and i think i got a bit better grasp on it now.

I have no idea. I did a quick test and it seems that staticmeshcomponent which has staticmesh slot allows direction assignment. Probably some kinda “after c++ construction method” (hidden from prying eyes unless one was to dig deep enough in engine code) was in play.
//.h
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = “C++”)
UStaticMesh * EdgeMesh;

// .cpp
EdgeMeshComponent->SetStaticMesh(EdgeMesh);

will have the same outcome as the material assignment.

Because at construction time the mesh you’ve specified isn’t loaded or set. Blueprint defaults are set later.

Constructor runs before anything, even before you load or open the blueprint.