I have a base actor class (AInteractableBase) from which several actors derive from. One of the main things this base class does is creating a dynamic material in the construction script, which is applied to the actor’s base mesh (EmissiveMesh).
My problem is when I try to spawn one of these actors from my GameMode.
This is my situation.
GameMode holds a TSubclassOf variable (LostBackpackObjectClass), whose EmissiveMesh is set to None.
When required, GameMode needs to create an instance of AInteractableBase (LostBackpackObject).
The mesh at this point is set with a certain mesh which uses a certain material. This is why LostBackpackObject, by default, doesn’t have an EmissiveMesh set: it changes every time I spawn it.
And this is where I’m stuck.
Since there is no default EmissiveMesh and associated material, the construction script doesn’t work, and when I finally set the EmissiveMesh I don’t have a dynamic material anymore.
I even tried manually calling the construction script from my code but it’s totally useless.
backpackMesh=gameInstance->GetLostBackpackMesh();
if(backpackMesh)
{
LostBackpackObject = Cast<AInteractableBase>(GetWorld()->SpawnActor(LostBackpackObjectClass));
// Modifying the mesh
LostBackpackObject->SetEmissiveMesh(backpackMesh);
LostBackpackObject->SetActorLocation(gameInstance->GetDeathLocation());
// Uselessly calling the construction script
LostBackpackObject->OnConstruction(LostBackpackObject->GetTransform());
}
If I however set a default mesh and material for my AInteractableBase object, everything works fine, but now I’m forced using a default material, with embarassing results:
I would put the cast in an if statement if it fails.
backpackMesh=gameInstance->GetLostBackpackMesh();
if(backpackMesh)
{
if(LostBackpackObject = Cast<AInteractableBase>){
(GetWorld()->SpawnActor(LostBackpackObjectClass));
// Modifying the mesh
LostBackpackObject->SetEmissiveMesh(backpackMesh);
LostBackpackObject->SetActorLocation(gameInstance->GetDeathLocation());
// Uselessly calling the construction script
LostBackpackObject->OnConstruction(LostBackpackObject->GetTransform());
}
}
Personally I would make all AInteractable implement an IInteractable interface and then just call it’s function via the interface.
No need to make this area of code handle what is part of the interactables job.
The spawning works, so that if statement always passes. It’s just the material that doesn’t get its dynamic version.
As for the interface, I am using an IInteractableInterface actually
I guess I could expand it a bit.
At any rate, I ended up giving up and just have SetEmissiveMesh as a BlueprintNativeEvent and basically calling the entire construction script code from scratch. it’s not too expensive since this would only be called when the player respawns so yeah, at least it works.
I just hoped to have a more clean way to achieve that.