Compute off the game thread, apply on it
The worker copies what it needs, runs the arithmetic in parallel, and hops back before touching the component.
void UTerrainAnalysisComponent::StartAnalysis()
{
// Copy the inputs. The background task must not read UObject state.
TArray<FVector> Points = CollectSamplePoints();
TWeakObjectPtr<UTerrainAnalysisComponent> WeakThis(this);
AsyncTask(
ENamedThreads::AnyBackgroundThreadNormalTask,
[Points = MoveTemp(Points), WeakThis]()
{
TArray<float> Scores;
Scores.SetNumUninitialized(Points.Num());
ParallelFor(Points.Num(), [&Points, &Scores](const int32 Index)
{
Scores[Index] = UE::ActionGame::Private::ScoreSample(Points[Index]);
});
AsyncTask(
ENamedThreads::GameThread,
[WeakThis, Scores = MoveTemp(Scores)]() mutable
{
if (UTerrainAnalysisComponent* Component = WeakThis.Get())
{
Component->ApplyScores(MoveTemp(Scores));
}
});
});
}- Why
- UObject state is only safe to read and write on the game thread. Copying the inputs up front means the background task never dereferences the component, and the weak pointer check covers destruction during the work.
- Costs
- Copying inputs costs memory and a pass over the data. The result also arrives a frame or more later, so the caller needs a defined state for "still working".
- Instead
- Use
ParallelForon its own when the work is short enough to block the game thread. UseFRunnableor a task graph chain when the job is long-lived rather than one pass.

