Runtime Instanced Static Mesh Tools by
Dear Community,
Hi everyone!
So I have an immediate solution for the issues people are having with instanced static mesh actors working in packaged games!
I’ve created two BP nodes that let you easily specify which actors you want to convert to Instanced Static Mesh Actors at runtime!
means that while in the editor, the actors are independent and can be moved around normally (the main advantage I sought to achieve with my ISM editor mode).
But once runtime starts, you can run my BP node to convert the actors of a specified blueprint/class to instanced static mesh actors!
The other node lets you quickly and easily iterate over Victory Instanced Static Mesh Actors (VictoryISM) that have been created during runtime!
**Make Dynamic Level Generation Super-Efficient!**
When dynamically generating levels your level unit size has to get smaller the more detailed and varied you want the levels to be. means that for detailed dynamically generated levels, you usually end up with a very high actor count!
**Well using my two new BP nodes, you can make dynamic level generation super-efficient** by turning 100s of actors sharing the same static mesh asset into a single static mesh!
Remember, the scaling, rotation, and translation of the static meshes can be anything you want!
Two New Advantages For You
The two new advantages of new system are:
a. You can use my BP nodes with actors that you have created yourself at runtime, such as for dynamically generated levels, MAZES, and such
b. ** system will work with packaged games,** since the instanced static mesh components do not need to serialize properly (as they currently dont seem to be doing). The serialization/cooking process becomes irrelevant since the actors are only converted to Instanced Static Mesh Actors at level start!
**Use of TMap, One Instanced Static Mesh Per Static Mesh Asset**
I use a C++ TMap to group the actors of the class you specify, and create as many instanced static mesh actors as are required.
Each Instanced Static Mesh Actor can only represent actors that **share the same static mesh asset**, so I group the found actors by their static mesh asset!
Here's the code where I do !
```
**//I want one array of actors for each unique static mesh asset! -**
TMap< UStaticMesh*,TArray<AActor*> > VictoryISMMap;
**//Note the ActorClass filter on the Actor Iterator! -**
for (TActorIterator<AActor> Itr(World, ActorClass); Itr; ++Itr)
{
**//Get Static Mesh Component!**
UStaticMeshComponent* Comp = Itr->FindComponentByClass<UStaticMeshComponent>();
if(!Comp) continue;
if(!Comp->IsValidLowLevel()) continue;
//~~~~~~~~~
**//Add Key if not present!**
if(!VictoryISMMap.Contains(Comp->StaticMesh))
{
VictoryISMMap.Add(Comp->StaticMesh);
VictoryISMMap[Comp->StaticMesh].Empty(); //ensure array is properly initialized
}
**//Add the actor!**
VictoryISMMap[Comp->StaticMesh].Add(*Itr);
}
```
Then, I loop over the TMap, and access the Array of actors that I created that share the same Static Mesh asset, and then turn the whole lot of them into a single Instanced Static Mesh Actor!
```
**//For each Static Mesh Asset in the Victory ISM Map**
for (TMap< UStaticMesh*,TArray<AActor*> >::TIterator It(VictoryISMMap); It; ++It)
{
**//Get the Actor Array for particular Static Mesh Asset!**
TArray<AActor*>& ActorArray = It.Value();
**//No entries?**
if(ActorArray.Num() < 1) continue;
//~~~~~~~~~~~~~~~~~~
**//Get the Root**
UStaticMeshComponent* RootSMC = ActorArray[0]->FindComponentByClass<UStaticMeshComponent>();
if(!RootSMC) continue;
//~~~~~~~~~~
**//Gather transforms!**
TArray<FTransform> WorldTransforms;
for(AActor* Each : ActorArray)
{
WorldTransforms.Add(Each->GetTransform());
//Destroy original?
if(DestroyOriginalActors)
{
Each->Destroy();
}
}
**//Create Victory ISM**
FActorSpawnParameters SpawnInfo;
SpawnInfo.bNoCollisionFail = true; //always create!
SpawnInfo.bDeferConstruction = false;
AVictoryISM* NewISM = World->SpawnActor<AVictoryISM>(
AVictoryISM::StaticClass(),
RootSMC->GetComponentLocation() ,
RootSMC->GetComponentRotation(),
SpawnInfo
);
if(!NewISM) continue;
//~~~~~~~~~~
**//Mesh**
NewISM->Mesh->SetStaticMesh(RootSMC->StaticMesh);
**//Materials**
const int32 MatTotal = RootSMC->GetNumMaterials();
for(int32 v = 0; v < MatTotal; v++)
{
NewISM->Mesh->SetMaterial(v,RootSMC->GetMaterial(v));
}
**//Set Transforms!**
for(const FTransform& Each : WorldTransforms)
{
NewISM->Mesh->AddInstanceWorldSpace(Each);
}
**//Add new ISM!**
CreatedISMActors.Add(NewISM);
}
**//Clear memory**
VictoryISMMap.Empty();
```
Easy to Edit, High Performance at Runtime!
The result of using my BP nodes to turn actors of a certain class to instanced static mesh actors is that you can now maintain easy editing of the actors while in the editor, and during game- still gain the performance advantages of converting a large number of actors that share the same static mesh asset into a single actor!
You can also now convert the large quantity of actors in dynamically generated levels into high performance instanced static mesh actors!
[FONT=Comic Sans MS]