Download

Passing a variable to FConstructorStatics

Hi all, I’m trying to create a base class for a bunch of helper actors that can be placed in the editor. These actors will have billboards and static meshes that are not visible in game. I want to be able to put all of the code to initialize these components in the base class, and create new classes that extend from the base class where a simple modification to some default variables define the resource paths for these billboards and meshes. I’m encountering the error **“a nonstatic member reference must be relative to a specific object” **on line 29. I understand that there is a way to pass in arguments, but I’m not sure of the exact syntax.



// Fill out your copyright notice in the Description page of Project Settings.

#include "EditorHelperObject.h"

// Sets default values
AEditorHelperObject::AEditorHelperObject(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
    // Disable Tick() every frame.
    PrimaryActorTick.bCanEverTick = false;

    SpriteTexturePath = FName(TEXT("/Engine/EditorResources/S_Note"));

    // Structure to hold one-time initialization
    struct FConstructorStatics
    {
        // A helper class object we use to find target UTexture2D object in resource package
        ConstructorHelpers::FObjectFinderOptional<UTexture2D> NoteTextureObject;

        // Icon sprite category name
        FName ID_Notes;

        // Icon sprite display name
        FText NAME_Notes;

        FConstructorStatics()
            // Use helper class object to find the texture
            // "/Engine/EditorResources/S_Note" is resource path
            : NoteTextureObject(SpriteTexturePath)
            , ID_Notes(TEXT("Notes"))
            , NAME_Notes(NSLOCTEXT("SpriteCategory", "Notes", "Notes"))
        {
        }
    };
    static FConstructorStatics ConstructorStatics;

    // We need a scene component to attach Icon sprite
    USceneComponent* SceneComponent = ObjectInitializer.CreateDefaultSubobject<USceneComponent>(this, TEXT("SceneComp"));
    RootComponent = SceneComponent;
    RootComponent->Mobility = EComponentMobility::Static;

#if WITH_EDITORONLY_DATA

    SpriteComponent = ObjectInitializer.CreateEditorOnlyDefaultSubobject<UBillboardComponent>(this, TEXT("Sprite"));
    if (SpriteComponent)
    {

        SpriteComponent->Sprite = ConstructorStatics.NoteTextureObject.Get();                                    // Get the sprite texture from helper class object
        SpriteComponent->SpriteInfo.Category = ConstructorStatics.ID_Notes;                                        // Assign sprite category name
        SpriteComponent->SpriteInfo.DisplayName = ConstructorStatics.NAME_Notes;                                // Assign sprite display name
        SpriteComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);    // Attach sprite to scene component
        SpriteComponent->Mobility = EComponentMobility::Static;
        SpriteComponent->bUseInEditorScaling = true;
    }
#endif // WITH_EDITORONLY_DATA
}

// Called when the game starts or when spawned
void AEditorHelperObject::BeginPlay()
{
    Super::BeginPlay();

}

// Called every frame
void AEditorHelperObject::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

}

I checked out NavigationObjectBase.cpp, and PlayerStart.cpp, which extends from ANavigationObjectBase, and I noticed that both have their own code to create and attach a billboard component. Does all of the constructor code really need to be typed again for child classes?

Why do you need FConstructorStatics to be static when you only use it inside constructor?

I am trying to learn by looking at existing code, so I’m doing it that way because that’s the only way I’ve seen it done. What would the alternative be?