- Create a new Actor called OnConstructionActor based on StaticMeshActor:
- Update the header file to the following:
#pragma once
#include "CoreMinimal.h"
#include "Engine/StaticMeshActor.h"
#include "OnConstructionActor.generated.h"
UCLASS()
class CHAPTER_09_API AOnConstructionActor : public AStaticMeshActor
{
GENERATED_BODY()
public:
AOnConstructionActor();
virtual void OnConstruction(const FTransform& Transform) override;
UPROPERTY(EditAnywhere)
bool ShowStaticMesh;
};
- Go to the implementation file (OnConstructionActor.cpp) and implement the class constructor:
#include "OnConstructionActor.h"
#include "ConstructorHelpers.h"
AOnConstructionActor::AOnConstructionActor()
{
// 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;
auto MeshAsset = ConstructorHelpers::FObjectFinder<UStaticMesh>(
TEXT("StaticMesh'/Engine/BasicShapes/Cone.Cone'"));
UStaticMeshComponent * SM = GetStaticMeshComponent();
if (SM != nullptr)
{
if (MeshAsset.Object != nullptr)
{
SM->SetStaticMesh(MeshAsset.Object);
SM->SetGenerateOverlapEvents(true);
}
SM->SetMobility(EComponentMobility::Movable);
}
// Default value of property
ShowStaticMesh = true;
}
- Implement OnConstruction:
void AOnConstructionActor::OnConstruction(const FTransform& Transform) { GetStaticMeshComponent()->SetVisibility(ShowStaticMesh); }
- Compile your code and launch the editor.
- Drag an instance of your class into the game world, and verify that toggling the Boolean value for ShowStaticMesh toggles the visibility of the mesh in the editor viewport:
- OnConstruction does not currently run for C++ actors that are placed in a level if they are moved.
- To test this, place a breakpoint in your OnConstruction function, and then move your actor around the level.
To place a breakpoint, place your cursor on the desired line and hit F9 in Visual Studio.
- You'll notice that the function doesn't get called, but if you toggle the ShowStaticMesh Boolean, it does, causing your breakpoint to trigger.
To see why, take a look at the beginning of the AActor::PostEditMove function:
void AActor::PostEditMove(bool bFinished)
{
if ( ReregisterComponentsWhenModified() && !FLevelUtils::IsMovingLevel())
{
UBlueprint* Blueprint = Cast<UBlueprint>(GetClass()->ClassGeneratedBy);
if (bFinished || bRunConstructionScriptOnDrag || (Blueprint && Blueprint->bRunConstructionScriptOnDrag))
{
FNavigationLockContext NavLock(GetWorld(), ENavigationLockReason::AllowUnregister);
RerunConstructionScripts();
}
}
// ....
The top line here casts UClass for the current object to UBlueprint, and will only run the construction scripts and OnConstruction again if the class is a Blueprint.