AActor::OnConstruction() called on every property change

Engine version: 4.6.1.

Description

If I try to change any property of my C+±class-derived-blueprint Actor (while playing in editor or not), it seems to get reconstructed everytime (Actor::OnConstruction() is called). Simply translating the object in the editor (not even in play mode) will trigger this. All the components on the Actor get destroyed and then reallocated (components pointing to new addresses), but PostInitComponents() is not called afterward. Is this working as intended? This seems very wasteful and causes a lot of problems when caching references to components in PostInitComponents().

Repro Steps

  • Create a new MyActor C++ class (MyActor.cpp/MyActor.h)

  • Override its OnConstruction method like so:

    void AMyActor::OnConstruction(const FTransform& Transform)
    {
    Super::OnConstruction(Transform);
    UE_LOG(LogTemp, Log, TEXT(“AMyActor::OnConstruction() called”));
    }

  • Create a blueprint BP_MyActor derived from the MyActor C++ class

  • Place an instance in the level

  • Observe that if you move the object around, you get spammed with OnConstruction() logs

  • Hit the PIE button

  • Observe that changing any other property of the Actor will cause the object to be reconstructed

You can also try adding components to the blueprint (e.g. PointLightComponent) and monitor its address using FindComponentByClass() in the OnConstruction() method. You will see a different pointer everytime you change a property of the actor or move it around.

Related Bug

This is the intended behavior of the construction script. You should not put your Component creation in there, the construction script whole purpose is to be called each time you modify a property of the actor so you can do custom “in editor” stuff related to that actor.

You can do Component creation in there, but yes, it will be flushed and re-done everytime. In permits lots of neat stuff like creating procedurally generated stuff :

It’s a very useful tool too!

See here for an example of it’s usage : - YouTube

Hm ok I wasn’t aware of this. My blueprint construction graph is empty, and I also don’t expect my entire list of components on my object to be recreated everytime I change a property of the object.

How do I cache reference to components in my C++ then? Right now this is causing my custom actor to be uneditable while in PIE mode because the components reset as soon as a property on the actor is modified. I’m currently caching the component references in MyActor::PostInitComponents() like so:

void MyActor::PostInitializeComponents()
{
	Super::PostInitializeComponents();

	SkyMesh = FindComponentByClass<UStaticMeshComponent>();
	SunLight = FindComponentByClass<UDirectionalLightComponent>();
	SkyLight = FindComponentByClass<USkyLightComponent>();

	CreateSkyMaterialInstance();
}

And I use these component references in the Actor’s Tick() method. This breaks as soon as I change a property on that actor while in PIE mode. Is there another event I should be monitoring, or some kind of tag/annotation I could use to tell the engine to not mess with these components?

I would use BeginPlay()

void MyActor::BeginPlay()
{
        //I don't know about FindComponentByClass, but an alternative would be this :
	TArray<UStaticMeshComponent*> staticMeshComps;
	GetComponents(staticMeshComps);
       //You will now have all your StaticMeshCompoenent in the staticMeshComps array
}

Hope That helps!

Hi Bugfoot,

I just wanted to check and see if Michaël’s answer helped you with this issue. Do you need any further help with this?

Tim