Construction Script for Actor Components

Hi,

Is it possible to have a construction script for Actor components? I am currently using the Actor Component to add additional functionality to existing actors, such as physics impact sounds, footstep sounds, flickering lights etc.

It is possible to use the BeginPay event to do some initial setup, however this could be costly when starting the game if the component is doing a lot of computation, or you have a bunch of actors using the Actor Component.

##Example
A flickering component that has to initially loop through components in the parent actor and create an array of light components, and create dynamic emissive material instances to be modified on the Tick event in response to a linear color curve.

This has to be done in BeginPlay, because there is no construction script for Actor Component (that I can find): Estranged Dev Blog #3: Blueprint Flickering Lights - YouTube


Could I request this as a feature if it isn’t possible already?

Thanks

1 Like

At the moment, no. But what you can do is make your component an actor instead and attach that as additional functionality to existing actors. It works but with that said, I’d prefer a construction script within the actor components.

1 Like

If you are creating your own custom Component, you can do this from within the function UActorComponent::PostInitProperties()

From there you call a BlueprintImplementableEvent that could act just like a Construction Script to initialize blueprint graph stuff.

3 Likes

I tried this:

UCLASS(BlueprintType, Blueprintable)
class MY_API AExtActor : public AActor
{
	GENERATED_BODY()
public:
	virtual void OnConstruction(const FTransform& Transform) override
	{
		for (UActorComponent* Component : GetComponents())
		{
			if (UExtActorComponent * ExtComp = Cast<UExtActorComponent>(Component))
			{
				ExtComp->ProcessConstructionScript(Transform);
			}
		}
	}
};

UCLASS(BlueprintType, Blueprintable)
class MY_API UExtActorComponent : public UActorComponent
{
	GENERATED_BODY()
public:
	void ProcessConstructionScript(const FTransform& Transform)
	{
		OnConstruction(Transform);

		ConstructionScript();
	}

	virtual void OnConstruction(const FTransform& Transform) {};

	UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "Construction Script"))
	void ConstructionScript();
};

Only OnConstruction method of AActor is virtual, but blueprint logics happened in UserConstructionScript which we can’t override in child class.

It works, but causes bugs and gives engine displeasure if ActorComponent “Construction Script” will add another components to actor…

  1. “Ensure condition failure” about changed components count in actor construction logics.

  2. Placed on scene this actor will snaps to zero coordinates.

  3. Creates two copies of component in actor (how second copy appeared I didn’t figured out, and one of copy will be also snapped to zero coordinates and can’t be moved with actor)

So that…

2021… child actors are well reputed to be buggy, and construction scripts are bugged in streaming levels. Sigh. :frowning:

3 Likes

It’s 2023 now I assume there’s no progress? Would be nice to inject logic into the GameState through components, if the components do initialization on a construction script…

1 Like

Its not work

UActorComponent::OnComponentCreated Fires in the editor. (For those that stumbled across this thread and just needed construction once)

1 Like

I would also like OnConstruction to be called for ActorComponents. The workaround mentioned above cause various problems.

1 Like

By default Unreal prevent blueprint scripts to run on editor. You nedd to add a FEditorScriptExecutionGuard at the scope that is calling the BlueprintImplementableEvent to enable script calls during editor run.
I added the required line surrounded by comments in the code below.

UCLASS(BlueprintType, Blueprintable)
class MY_API AExtActor : public AActor
{
	GENERATED_BODY()
public:
	virtual void OnConstruction(const FTransform& Transform) override
	{
		for (UActorComponent* Component : GetComponents())
		{
			if (UExtActorComponent * ExtComp = Cast<UExtActorComponent>(Component))
			{
				ExtComp->ProcessConstructionScript(Transform);
			}
		}
	}
};

UCLASS(BlueprintType, Blueprintable)
class MY_API UExtActorComponent : public UActorComponent
{
	GENERATED_BODY()
public:
	void ProcessConstructionScript(const FTransform& Transform)
	{
        /////////// Just add this line /////////////
        FEditorScriptExecutionGuard ScriptGuard
		////////////////////////////////////////////
		OnConstruction(Transform); 
        ConstructionScript();
	}

	virtual void OnConstruction(const FTransform& Transform) {};

	UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "Construction Script"))
	void ConstructionScript();
};

What’s the bug with streaming levels?

They don’t run construction scripts. Granted, I haven’t tested this in a couple of years to see if Epic fixed it, but I’ve learned to not get my hopes up…

Hello everyone,

Personally, to have the equivalent of a ConstructScript able to perform operations on the parent (or another component) and also be executed in the editor, I use the OnRegister() function.

What do I actually do?

  1. In C++, I create a class inheriting from ActorComponent, which we call AC_Base. This class is Blueprintable.

  2. I declare an OnThisRegister() function which is BlueprintImplementableEvent.

  3. I override OnRegister() so that it calls my OnThisRegister() method.

  4. I inherit my next (Blueprint) actor components from AC_Base.

  5. I implement the event OnThisRegister() in the Blueprints.

I’ll leave you with the header and source code for AC_Base.

Hope this helps.

AC_Base.h (803 Bytes)
AC_Base.cpp (891 Bytes)

2 Likes

try to override PostEditChangeProperty.

// .h file
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
// .cpp file
void UYourComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
	Super::PostEditChangeProperty(PropertyChangedEvent);
}