I am making an actor that spawns another actor on BeginPlay()
. The appearance of the actor changes depending on an FName
member of the spawning actor. When that FName
is changed, it looks up a value from a data table to change the appearance. (If an item could not be found that matches the FName, it will display a sprite instead and won’t spawn anything.)
In other words, this:
AAGDroppedItemSpawner::AAGDroppedItemSpawner() : Super()
{
SphereCollision = CreateDefaultSubobject<USphereComponent>(TEXT("SphereCollision"));
SphereCollision->ShapeColor = FColor(76, 255, 76, 255);
//SphereCollision->bOnlyDrawIfSelected = true;
SphereCollision->bShouldCollideWhenPlacing = true;
SphereCollision->SetShouldUpdatePhysicsVolume(true);
SphereCollision->Mobility = EComponentMobility::Static;
RootComponent = SphereCollision;
ItemNotFoundSprite = CreateEditorOnlyDefaultSubobject<UBillboardComponent>(TEXT("ItemNotFoundSprite"));
ItemFoundMesh = CreateEditorOnlyDefaultSubobject<UStaticMeshComponent>(TEXT("ItemFoundMesh"));
#if WITH_EDITORONLY_DATA
if (!IsRunningCommandlet())
{
// Structure to hold one-time initialization
struct FConstructorStatics
{
ConstructorHelpers::FObjectFinderOptional<UTexture2D> NavigationTextureObject;
FName ID_ActorSprite;
FText NAME_ActorSprite;
ConstructorHelpers::FObjectFinderOptional<UTexture2D> ItemNotFoundSpriteObject;
FConstructorStatics()
: NavigationTextureObject(TEXT("/Engine/EditorResources/S_Actor"))
, ID_ActorSprite(TEXT("Actor"))
, NAME_ActorSprite(NSLOCTEXT("SpriteCategory", "Actor", "Actor"))
, ItemNotFoundSpriteObject(TEXT("/Engine/EditorResources/Bad"))
{
}
};
static FConstructorStatics ConstructorStatics;
if (ItemNotFoundSprite)
{
ItemNotFoundSprite->Sprite = ConstructorStatics.ItemNotFoundSpriteObject.Get();
ItemNotFoundSprite->bHiddenInGame = true;
ItemNotFoundSprite->SpriteInfo.Category = ConstructorStatics.ID_ActorSprite;
ItemNotFoundSprite->SpriteInfo.DisplayName = ConstructorStatics.NAME_ActorSprite;
ItemNotFoundSprite->SetUsingAbsoluteScale(true);
ItemNotFoundSprite->SetupAttachment(SphereCollision);
ItemNotFoundSprite->bIsScreenSizeScaled = true;
}
}
#endif // WITH_EDITORONLY_DATA
// We don't have a proper default ItemKind so just show the not found sprite for now
if (ItemNotFoundSprite)
{
ItemNotFoundSprite->SetVisibility(true);
}
}
void AAGDroppedItemSpawner::BeginPlay()
{
Super::BeginPlay();
// Spawn the item!
// Destroy itself once we are done
Destroy();
}
#if WITH_EDITOR
void AAGDroppedItemSpawner::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
const FName PropertyName = PropertyChangedEvent.Property ? PropertyChangedEvent.Property->GetFName() : NAME_None;
if (PropertyName == NAME_ItemKind)
{
ValidateMeshDisplay();
}
MarkComponentsRenderStateDirty(); // force redisplay
Super::PostEditChangeProperty(PropertyChangedEvent);
}
void AAGDroppedItemSpawner::PostEditUndo()
{
Super::PostEditUndo();
ValidateMeshDisplay();
}
#endif // WITH_EDITOR
void AAGDroppedItemSpawner::ValidateMeshDisplay()
{
if (!GEditor || !ItemNotFoundSprite || !ItemFoundMesh)
{
return;
}
AAGGameState* GameState = GEditor->PlayWorld->GetGameState<AAGGameState>();
if (!GameState || !GameState->AllItemData)
{
ItemNotFoundSprite->SetVisibility(true);
ItemFoundMesh->SetVisibility(false);
}
FItemData* ItemData = GameState->AllItemData->FindRow<FItemData>(ItemKind, TEXT("AAGDroppedSpawner::ValidateMeshDisplay"), false);
if (ItemData && ItemData->ItemMesh)
{
ItemNotFoundSprite->SetVisibility(false);
ItemFoundMesh->SetStaticMesh(ItemData->ItemMesh);
ItemFoundMesh->SetVisibility(true);
}
else
{
ItemNotFoundSprite->SetVisibility(true);
ItemFoundMesh->SetVisibility(false);
}
}
The problem with this is that there’s no gamestate, since this is in the editor, and GameState is NULL
. Also, ValidateMeshDisplay
isn’t called at the beginning of the editor session, so everything displays the sprite instead.
Basically, I want a preview of the actor before it spawns, but the appearance depends on data in a data sheet. Should I move the data sheet to be somewhere besides the game state, and if so, where? If I don’t need to move it, how do I edit the code to get the appearance?