My game involves many actors, with the same skeletal mesh, who from time to time will change materials depending on their allegiance.
i.e., an actor’s ChangeAllegiance(…) method will do a USkeletalMesh->SetMaterial() call.
However, I’m trying to figure out the most approprate place to summon these assets from. My goal is to hold the least amount of information on this per-actor and maybe get what they need from some static BlueprintUtility resource?
As far as I’m aware you can’t load resources in BlueprintUtility libraries because they have no Constructor and hence can’t use ConstructorHelpers::FFindObject.
However, I do appear to be able to load resources anywhere, at any time, using **StaticLoadObject **?
Q: Why would I ever use FFindObject when I can use StaticLoadObject where there seems to be no caveat or downside?
The following is just some extra information on how I’m currently doing this with FFindObject in the constructor
At the moment, each Actor has:
TMap<EAllegiance, UMaterialInstance*> Uniforms;
and this is loaded statically in the constructor:
static ConstructorHelpers::FObjectFinder<UMaterialInterface> WhiteUniform(TEXT("MaterialInstanceConstant'/Game/Materials/Knight_White.Knight_White'"));
static ConstructorHelpers::FObjectFinder<UMaterialInterface> RedUniform(TEXT("MaterialInstanceConstant'/Game/Materials/Knight_Red.Knight_Red'"));
static ConstructorHelpers::FObjectFinder<UMaterialInterface> YellowUniform(TEXT("MaterialInstanceConstant'/Game/Materials/Knight_Yellow.Knight_Yellow'"));
static ConstructorHelpers::FObjectFinder<UMaterialInterface> BlueUniform(TEXT("MaterialInstanceConstant'/Game/Materials/Knight_Blue.Knight_Blue'"));
if (WhiteUniform.Succeeded() && RedUniform.Succeeded() && YellowUniform.Succeeded() && BlueUniform.Succeeded()) {
Uniform.Add(EAllegiance::White, WhiteUniform.Object);
Uniform.Add(EAllegiance::Red, RedUniform.Object);
Uniform.Add(EAllegiance::Yellow, YellowUniform.Object);
Uniform.Add(EAllegiance::Blue, BlueUniform.Object);
}
else {
UE_LOG(LogTemp, Error, TEXT("UNABLE TO FIND MATERIAL"));
}
This means if I have thousands of Actors, each has a TMap of possible UMaterialInstance*. Not too system intensive, but not a great design decision?
Is there a way I could get these assets loaded in C++ at runtime into a BlueprintUtility and be able to call something like:
void ChangeAllegiance(EAllegiance a) {
UMaterialInstance* mat = UGameUtility::GetUniformMaterial(a);
SkeletalMesh->SetMaterial(0, mat);
}
It’s mostly about getting these resources initialised at the beginning and having them globally available to any actor.