I’m trying to generate a terrain procedurally. On tick, I check to see which tiles fall within a specific radius from where the player is and if they are not drawn, draw them as a new section via the procedural mesh component attached to the actor.
I’m dispatching a worker thread to handle geometry generation, which could take a few seconds. However, drawing them as a section on the procedural mesh component MUST be done in the game thread. There’s an assertion check somewhere in the call. This means that after the player approaches a new tile and it has been generated, there’s a noticeable 1-second lag when the game hangs before the tile is added and the game thread continues working again.
void ATerrain::AsyncDrawTile(int32 TileX, int32 TileY) {
UE_LOG(LogTemp, Display, TEXT("ATerrain::AsyncDrawTile(%d, %d)"), TileX, TileY);
// Dispatching a worker thread to generate the tile data.
AsyncTask(ENamedThreads::AnyThread, [this, TileX, TileY]() {
FTileData TileData;
UKismetProceduralMeshLibrary::CreateGridMeshWelded(...);
// Adjusting the location of the vertices.
for (auto &Vertex: TileData.Vertices) {...}
// Calculating normals and tangents. Quadratic complexity. It's going to take a while.
UKismetProceduralMeshLibrary::CalculateTangentsForMesh(...);
// Jumping back to the game thread because CreateMeshSection can only be called from the game thread.
AsyncTask(ENamedThreads::GameThread, [this, TileX, TileY, TileData]() {
// Clearing the section if it exists, or getting a new section index.
const auto SectionIndex = GetClearSection(TileX, TileY);
// Adding the mesh section to the vertex buffer.
ProcMeshComp->CreateMeshSection(
SectionIndex,
TileData.Vertices,
TileData.Triangles,
TileData.Normals,
TileData.UV0,
TileData.VertexColors,
TileData.Tangents,
true // Collisions
);
// Assigning the auto material if any is set.
if (Material) {
ProcMeshComp->SetMaterial(SectionIndex, Material);
}
});
});
}
Is there any workarounds or alternative methods that would avoid blocking the game thread?
Thanks.