What is the way to generate collision data with better performance ?

I am trying to create something similiar to UE’s landscape but with different features.That looks like this: Unreal Engine Dynamic Landscape - YouTube

For my purpose I use:

DMC->SetComplexAsSimpleCollisionEnabled(true, true);

Setting above works perfect with low performance during construction.

I tried to generate collision manually. For now this code works and creates simple collision:

void ATerrainActor::CustomCollisionA(UDynamicMeshComponent* dmc) {
	if (!IsValid(dmc)) return;

	dmc->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	UBodySetup* BodySetup = dmc->GetBodySetup();
	if (BodySetup)
	{
		BodySetup->Modify(); // Editördeysen değişikliği işaretle
		BodySetup->AggGeom.EmptyElements(); // Eski collisionları sil
		FKBoxElem Box;
		Box.SetTransform(FTransform::Identity);
		Box.X = 2000.0f; Box.Y = 2000.0f; Box.Z = 200.0f; // Net boyutlar
		BodySetup->AggGeom.BoxElems.Add(Box);
		BodySetup->CollisionTraceFlag = ECollisionTraceFlag::CTF_UseSimpleAsComplex;
		BodySetup->CollisionReponse = EBodyCollisionResponse::BodyCollision_Enabled;
		BodySetup->InvalidatePhysicsData();
		BodySetup->CreatePhysicsMeshes();
	}
	dmc->SetCollisionProfileName(UCollisionProfile::BlockAll_ProfileName);
	dmc->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
	dmc->RecreatePhysicsState();
	UE_LOG(LogTemp, Warning, TEXT("Collision Yenilendi. Box Sayisi: %d"), dmc->GetBodySetup()->AggGeom.BoxElems.Num());

	dmc->SetCollisionProfileName(TEXT("BlockAll"));
	dmc->SetCollisionObjectType(ECC_WorldStatic);
	dmc->SetCollisionResponseToAllChannels(ECR_Block);
	dmc->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block);
	dmc->GetBodyInstance()->UpdatePhysicsFilterData();
}

If I use TriMeshGeometries it does not work:

void ATerrainActor::BuildCustomTriMeshGeometryCollision(UDynamicMeshComponent* dmc) {

    if (!IsValid(dmc)) return;

    UBodySetup* BodySetup = dmc->GetBodySetup();

    if (!BodySetup) return;

    BodySetup->Modify();

    BodySetup->InvalidatePhysicsData();

    BodySetup->AggGeom.EmptyElements();

    BodySetup->TriMeshGeometries.Empty();



    TArray<FVector3f> ChaosVertices;

    ChaosVertices.Add(FVector3f(0.f, 0.f, 600.f));

    ChaosVertices.Add(FVector3f(512.f, 0.f, 600.f));

    ChaosVertices.Add(FVector3f(0.f, 512.f, 600.f));



    Chaos::TParticles<FRealSingle, 3> Particles;

    Particles.AddParticles(ChaosVertices.Num());

    for (int32 i = 0; i < ChaosVertices.Num(); ++i) {

        Particles.X(i) = Chaos::TVector<FRealSingle, 3>(ChaosVertices[i]);

    }


    TArray<uint16> MaterialIndices;

    MaterialIndices.Add(0);




    TArray<Chaos::TVec3<int32>> ChaosTriangles;

    ChaosTriangles.Add(Chaos::TVec3<int32>(0, 1, 2));



    Chaos::FTriangleMeshImplicitObjectPtr trimeshgeometry =

        Chaos::FTriangleMeshImplicitObjectPtr(new Chaos::FTriangleMeshImplicitObject(

            MoveTemp(Particles), MoveTemp(ChaosTriangles), MoveTemp(MaterialIndices), nullptr, nullptr, false));



    BodySetup->TriMeshGeometries.Add(trimeshgeometry);

    BodySetup->CreatePhysicsMeshes();

    BodySetup->CollisionTraceFlag = ECollisionTraceFlag::CTF_UseComplexAsSimple;



    BodySetup->bHasCookedCollisionData = true;

    BodySetup->bNeverNeedsCookedCollisionData = true; // Motorun tekrar 'DataProvider'a gitmesini engellemeye çalışır

    dmc->UpdateBounds();



    dmc->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);

    dmc->SetCollisionProfileName(UCollisionProfile::BlockAll_ProfileName);

    dmc->RecreatePhysicsState();

}

What I need to do?