I modified it a little bit to fit the runtime conversion.
void URuntimeToolBPLibrary::DynamicToStaticMesh(const UDynamicMesh* DynamicMesh, const FName Name, UStaticMesh*& StaticMesh)
{
if (DynamicMesh == nullptr)
return;
const UWorld* World = DynamicMesh->GetWorld();
UStaticMesh* LocalStaticMesh = NewObject<UStaticMesh>(World->GetCurrentLevel(), Name, RF_Transient);
LocalStaticMesh->bAllowCPUAccess = true;
LocalStaticMesh->bSupportGpuUniformlyDistributedSampling = true;
LocalStaticMesh->SetLightingGuid();
FMeshDescription MeshDescription;
FStaticMeshAttributes StaticMeshAttributes(MeshDescription);
StaticMeshAttributes.Register();
const FDynamicMesh3* Mesh = DynamicMesh->GetMeshPtr();
FDynamicMeshToMeshDescription Converter;
Converter.Convert(Mesh, MeshDescription);
TArray<const FMeshDescription*> MeshDescriptionPtrs;
MeshDescriptionPtrs.Emplace(&MeshDescription);
UStaticMesh::FBuildMeshDescriptionsParams mdParams;
//mdParams.bBuildSimpleCollision = true;
mdParams.bFastBuild = true;
mdParams.bAllowCpuAccess = true;
mdParams.bCommitMeshDescription = true;
LocalStaticMesh->BuildFromMeshDescriptions(MeshDescriptionPtrs, mdParams);
FStaticMeshRenderData* LocalStaticMeshRenderData = LocalStaticMesh->GetRenderData();
FStaticMeshLODResources* LocalStaticMeshLODResources = const_cast<FStaticMeshLODResources *>(LocalStaticMeshRenderData->GetCurrentFirstLOD(0));
if (LocalStaticMeshLODResources && LocalStaticMeshLODResources->Sections.Num() > 0)
{
for (int i = 0; LocalStaticMeshLODResources->Sections.Num() > i; i++)
{
LocalStaticMeshLODResources->Sections[i].MaterialIndex = 0;
}
}
StaticMesh = LocalStaticMesh;
}