How to use OnConstruction in C++?

Hi everyone! Without wasting your time I will explain the situation clearly and to the point.

I want to set the material for the skeletal mesh using C++ and I want to do it under constructor but the problem is constructor is calling the function before the editor loads or before the skeletal mesh even created, but the same time the editor is not letting me this to know and I figured it out myself by implementing the same function using blueprints and it works perfectly implementing and calling on blueprint constructor. But the C++ thing is very not logical and very different.

C++ version is only printing SUCCESS: Head material: ID (3) and not effecting anything in reality and not setting the material but it logs the material is sets up which is not true.

I want to know How can I Implement or call this function using OnConstruction to give it a try if it will work hopefully.

void AMyCharacter::SetSkeletalMeshMaterial()
{
static ConstructorHelpers::FObjectFinder<UMaterialInterface>Material(TEXT("/Game/Assets/Materials/HeadMaterial"));
	DynamicMaterial_HeadRef = UMaterialInstanceDynamic::Create(Material.Object, this, FName("HeadMaterial"));
	if (Material.Succeeded())
	{
		if (MainMesh != nullptr)
		{
		MainMesh->SetMaterialByName(MatSocketHead, DynamicMaterial_HeadRef); 
		print("SUCCESS: Head material: ID (3)");
		}
	}
	else
	{
		print("FAILED: Head Material: ID (3)");
	}
}

Function:


Constructor:

3 Likes

The Constructor and OnConstruction() are different things. Since you’re using ConstructorHelpers, I can tell the function in called by the constructor, i.e. by your AMyCharacter::AMyCharacter() function.

OnConstruction() is a separate function that you can override, and it corresponds to blueprints’ ConstructionScript.

.h:

void OnConstruction(const FTransform &Transform) override;

.cpp

void AMyCharacter::OnConstruction(const FTransform &Transform)
{
    Super::OnConstruction(Transform);
    //Your Logic Here
}

Try using OnConstruction() for your materials, but leave ConstructorHelpers stuff in the Constructor, obviously.

Plus, note that every variable you change OnConstruction() must be UPROPERTY(), otherwise it will be defaulted on BeginPlay();

8 Likes

in UE constructor should only be used to set defaults it does not work same as blueprint construction script, closest equivalent is actually “Class Defaults”

For constcution script in C++ you need to override this function:

There also ton of other events that you can hook on if you explore AActor API reference, also
ConstructorHelpers don’t work outside constructor, you can read how to reference assets here Referencing Assets | Unreal Engine 4.27 Documentation

5 Likes

Thank You Sir for reply and helping me, it helps me alot but the problem is still not solved, OnConstruction is still not changing/setting the material , just printing success material but not effecting anything.
I am accepting your answer as it already answered how to use OnConstruction thank U

1 Like

Thank You very much Sir , I learned alot from this post but still not solved the issue… I will look for another solution or I will just implement this function in blueprints.

1 Like
Ok, so running this code in the constructor sets and found the material in StoredMaterial as you can see in the editor. But Dynamic Material Inst has got this yellow undo arrow, pressing this the material loads in it and if I press compile the material removed automatically and this yellow arrow appeared.
static ConstructorHelpers::FObjectFinder<UMaterial>FoundMaterial(TEXT("/Game/Assets/Materials/DM_FH_01"));
	if (FoundMaterial.Succeeded())
	{
		StoredMaterial = FoundMaterial.Object;
	}
DynamicMaterialInst = UMaterialInstanceDynamic::Create(StoredMaterial, MainMesh);
	if (DynamicMaterialInst != nullptr)
	{
		MainMesh->SetMaterial(3, DynamicMaterialInst);
	}
	else
	{
		print("Failed");
	}

and running this part in the begin play sets the material correctly in the Dynamic Material Inst when I play the game

DynamicMaterialInst = UMaterialInstanceDynamic::Create(StoredMaterial, MainMesh);
	if (DynamicMaterialInst != nullptr)
	{
		MainMesh->SetMaterial(3, DynamicMaterialInst);
	}
1 Like

Hi ,

it is a bit off-topic but I think many would find it interesting.
Do you know what the difference is between AActor::UserConstructionScript() and AActor::OnConstruction()?

Isn’t UserConstructionScript() a function that’s used by the blueprint construction?
Like widgets have Construct() and NativeConstruct(), for blueprints and c++ respectively.

Ok, so what does this mean in practical terms? Would you use AActor::UserConstructionScript() or rather AActor::OnConstruction() if you want some construction functions carried out in C++?

I’ve never used UserConstructionScript();
OnConstruction() does everything you need.
Maybe if you have some functionality in the blueprint constructor and you want the blueprint script to run before the c++ script, maybe you can use UserConstructionScript() and call the parent function from BP when you need it, but it’s just a wild guess, IDK.
OnConstruction() worked for me every time.

Hi, while this forum post was long answered, here an addition as some people may find it useful.

OnConstruct is called after the Blueprint’s components have been created and registered, so it shouldn’t be used to inform the UserConstructionScript.

Since there is a general misunderstanding that OnConstruct is the C++ equivalent of the BP construction script, here a response I got from Jon Lambert from Epic Games in quote:

"
AActor::UserConstructionScript is the BlueprintImplementable event that is called the “Construction Script” in the Blueprint Editor. It’s a common misconception, but the OnConstruction function is not really meant to be the native equivalent of the UserConstructionScript, a.k.a. Blueprint Construction Script. OnConstruct is called after the Blueprint’s components have been created and registered, so it shouldn’t be used to inform the UserConstructionScript, but it’s good for setting values or running some post construction setup. The reason it works in the level editor, but not in a spawned actor is because OnConstruct get’s a chance to run before subsequent reruns of the UserConstructionScript that occur while you are editing the instance. When spawning the actor, ExecuteConstruction is only run once, so the property isn’t set in time for your construction script. In your case, it sounds like you could move the logic out of OnConstruct and into a Blueprint Callable function and call that from your BP’s construction script.
"

You should not use OnConstruct as a C++ equivalent of BP Construction script, instead create blueprint callable C++ functions which you then call from the construction script.

4 Likes

On Constuct() did not work for me in some cases (whenever I calculated something which then should be used by the construction script).

So I digged some more:

here a response I got from Jon Lambert from Epic Games in quote:

"
AActor::UserConstructionScript is the BlueprintImplementable event that is called the “Construction Script” in the Blueprint Editor. It’s a common misconception, but the OnConstruction function is not really meant to be the native equivalent of the UserConstructionScript, a.k.a. Blueprint Construction Script. OnConstruct is called after the Blueprint’s components have been created and registered, so it shouldn’t be used to inform the UserConstructionScript, but it’s good for setting values or running some post construction setup. The reason it works in the level editor, but not in a spawned actor is because OnConstruct get’s a chance to run before subsequent reruns of the UserConstructionScript that occur while you are editing the instance. When spawning the actor, ExecuteConstruction is only run once, so the property isn’t set in time for your construction script. In your case, it sounds like you could move the logic out of OnConstruct and into a Blueprint Callable function and call that from your BP’s construction script.
"
You cannot have a function body for UserConstructionScript in c++ because it is a BlueprintImplementableEvent.

Good to know. So I was right that it was the blueprint equivalent, but I was wrong about the priority.