Procedural mesh not saving all of its sections to static mesh

I think I found a working solution, which works fine in UE_5.0.3 game runtime.

Mostly it was copied from original FProceduralMeshComponentDetails::ClickedOnConvertToStaticMesh() source code. Unfortunatly it failed to package game binaries. So I spent 2 days looking for alternative solution.

Generally I replaced original mesh description commitment [starting from AddSourceModel()], which for whatever reason works only in Editor.

Also make sure you AddCollisionConvexMesh supplied with convex mesh vertices (the same mesh vertices for me) to ProceduralMeshComponent before converting it to StaticMesh if you want your simple collision to work properly. Toggle bUseComplexAsSimpleCollision flag on your ProceduralMeshComponent to false as well.

// PrivateDependencyModuleNames.AddRange(new string[] { "ProceduralMeshComponent", "MeshDescription",  });

#include "ProceduralMeshComponent.h"
#include "ProceduralMeshConversion.h"
#include "StaticMeshDescription.h"

UStaticMesh* ULifeUtils::TestFunc(UProceduralMeshComponent* ProcMesh)
{
	if (!ProcMesh)
		return nullptr;
	
	FMeshDescription MeshDescription = BuildMeshDescription(ProcMesh);

	// If we got some valid data.
	if (MeshDescription.Polygons().Num() > 0)
	{
		// Create StaticMesh object
		UStaticMesh* StaticMesh = NewObject<UStaticMesh>(ProcMesh/*Package, MeshName, RF_Public | RF_Standalone*/);
		StaticMesh->InitResources();

		StaticMesh->SetLightingGuid();

		// Add source to new StaticMesh
		auto Desc = StaticMesh->CreateStaticMeshDescription();
		Desc->SetMeshDescription(MeshDescription);
        // buildSimpleCol = false, cause it creates box collision based on mesh bounds or whatever :(
		StaticMesh->BuildFromStaticMeshDescriptions({ Desc }, false); 

		//// SIMPLE COLLISION
		if (!ProcMesh->bUseComplexAsSimpleCollision )
		{
			StaticMesh->CreateBodySetup();
			UBodySetup* NewBodySetup = StaticMesh->GetBodySetup();
			NewBodySetup->BodySetupGuid = FGuid::NewGuid();
			NewBodySetup->AggGeom.ConvexElems = ProcMesh->ProcMeshBodySetup->AggGeom.ConvexElems;
			NewBodySetup->bGenerateMirroredCollision = false;
			NewBodySetup->bDoubleSidedGeometry = true;
            // Play around with the flag below if you struggle with collision not working
			NewBodySetup->CollisionTraceFlag = CTF_UseDefault;
			NewBodySetup->CreatePhysicsMeshes();
		}
		
		/* Commented out cause I don't need it
		//// MATERIALS
		TSet<UMaterialInterface*> UniqueMaterials;
		const int32 NumSections = ProcMesh->GetNumSections();
		for (int32 SectionIdx = 0; SectionIdx < NumSections; SectionIdx++)
		{
			FProcMeshSection *ProcSection =
				ProcMesh->GetProcMeshSection(SectionIdx);
			UMaterialInterface *Material = ProcMesh->GetMaterial(SectionIdx);
			UniqueMaterials.Add(Material);
		}
		// Copy materials to new mesh
		for (auto* Material : UniqueMaterials)
		{
			StaticMesh->GetStaticMaterials().Add(FStaticMaterial(Material));
		}
		*/

		// Uncallable in game runtime
		// StaticMesh->Build(false);

		return StaticMesh;
	}

	return nullptr;
}
2 Likes