The Problem
I’m creating a landscape using an InstancedStaticMeshComponent using noise. The calculations were taking up too much of the game thread, so I decided to put it on a separate thread. The problem seems to be that the task executes too fast and leaves gaps in my landscape.
FPlatformProcess::Sleep(0.01f);
but that takes forever to generate my landscape and also has the same issue if I switch windows and the framerate drops.The Code
This is the shortened version of the class responsible for creating the landscape
class FAsyncWorldCreation : public FNonAbandonableTask
{
friend class FAutoDeleteAsyncTask<FAsyncWorldCreation>;
public:
DECLARE_DELEGATE_TwoParams(FAsyncGenerationCompleted, FAsyncPartitionGrid, FAsyncTileReturn)
DECLARE_DELEGATE_TwoParams(FTileReturnCall, FTransform, int32)
UPROPERTY()
FAsyncGenerationCompleted OnAsyncCreateComplete;
UPROPERTY()
FTileReturnCall TestTileReturn;
FAsyncWorldCreation(AWorldGenerator* InWorld, bool bNoTrees, bool bNoSeed);
void DoWork();
FORCEINLINE TStatId GetStatId() const { // Probably declares the Task to the TaskGraph
RETURN_QUICK_DECLARE_CYCLE_STAT(FAsyncWorldCreation, STATGROUP_ThreadPoolAsyncTasks);
}
private:
UPROPERTY()
TWeakObjectPtr<AWorldGenerator> WorldRef;
FAsyncTileReturn AsyncGenerateWorld(FAsyncPartitionGrid& ReturnWorld);
};
And this is how I create the new Task
AsyncTask(ENamedThreads::AnyHiPriThreadHiPriTask, [&]()
{
(new FAutoDeleteAsyncTask<FAsyncWorldCreation>(this, bNoTrees, bDontGenerateSeed))->StartBackgroundTask();
});
To generate the landscape I nest the Y loop in the X loop, and for every Y tile created I execute a delegate that adds an instance to the component. I have very little knowledge with multithreading, so I have no idea how to solve this.
The Question
How can I do the calculations on a separate thread without slowing the thread down and still have the landscape generate properly.
EDIT
After some more testing, it seems to be something with the way the delegate is executed. If I execute this after every Y tile
AsyncTask(ENamedThreads::GameThread, [&]()
{
TestTileReturn.ExecuteIfBound(InstanceTransform, LandType);
//UE_LOG(LogTemp, Warning, TEXT("X: %d, Y: %d"), xi, yi)
});
it generates the whole world with holes in it. However, if I change the &
to a =
It doesn’t generate wholes, but it also doesn’t generate the whole world.