Create procedural mesh from animated skeletal mesh?

I had some problems with a skeletal mesh that contain multiple RenderSections and also different vector types in UE5 (i guess?)
here’s updated example code that accounts for multiple render section and properly copies all render sections

To make different section with different materials to work properly you also need to fill in “triangles” array properly accounting for each section BaseIndex and keeping in mind that index buffer array is multiple of 3 respective to “triangle index” of a section

Here is updated code that work for me.

void CopySkeletalMeshToProcedural(USkeletalMeshComponent* SkeletalMeshComponent, int32 LODIndex, UProceduralMeshComponent* ProcMeshComponent)
{
	FSkeletalMeshRenderData* SkMeshRenderData = SkeletalMeshComponent->GetSkeletalMeshRenderData();
	const FSkeletalMeshLODRenderData& DataArray = SkMeshRenderData->LODRenderData[LODIndex];
	FSkinWeightVertexBuffer& SkinWeights = *SkeletalMeshComponent->GetSkinWeightBuffer(LODIndex);

	TArray<FVector> VerticesArray;
	TArray<FVector> Normals;
	TArray<FVector2D> UV;
	TArray<FColor> Colors;
	TArray<FProcMeshTangent> Tangents;

	for (int32 j = 0; j < DataArray.RenderSections.Num(); j++)
	{
		//get num vertices and offset 
		const int32 NumSourceVertices = DataArray.RenderSections[j].NumVertices;
		const int32 BaseVertexIndex = DataArray.RenderSections[j].BaseVertexIndex;
		
		for (int32 i = 0; i < NumSourceVertices; i++)
		{
			const int32 VertexIndex = i + BaseVertexIndex;

			//get skinned vector positions
			const FVector3f SkinnedVectorPos = USkeletalMeshComponent::GetSkinnedVertexPosition(
				SkeletalMeshComponent, VertexIndex, DataArray, SkinWeights);
			VerticesArray.Add(fromFVector3f(SkinnedVectorPos));

			//Calc normals and tangents from the static version instead of the skeletal one
			const FVector3f ZTangentStatic = DataArray.StaticVertexBuffers.StaticMeshVertexBuffer.VertexTangentZ(
				VertexIndex);
			const FVector3f XTangentStatic = DataArray.StaticVertexBuffers.StaticMeshVertexBuffer.VertexTangentX(
				VertexIndex);

			//add normals from the static mesh version instead because using the skeletal one doesnt work right.
			Normals.Add(fromFVector3f(ZTangentStatic));

			//add tangents
			Tangents.Add(FProcMeshTangent(fromFVector3f(XTangentStatic), false));

			//get UVs
			const FVector2f SourceUVs = DataArray.StaticVertexBuffers.StaticMeshVertexBuffer.
			                                      GetVertexUV(VertexIndex, 0);
			FVector2d ResUVs;
			ResUVs.X = SourceUVs.X;
			ResUVs.Y = SourceUVs.Y;
			UV.Add(ResUVs);

			//dummy vertex colors
			Colors.Add(FColor(0.0, 0.0, 0.0, 255));
		}
	}

	//get index buffer
	FMultiSizeIndexContainerData IndicesData;
	DataArray.MultiSizeIndexContainer.GetIndexBuffer(IndicesData.Indices);


	for (int32 j = 0; j < DataArray.RenderSections.Num(); j++)
	{
		TArray<int32> Tris;

		// get number triangles and offset
		const int32 SectionNumTriangles = DataArray.RenderSections[j].NumTriangles;
		const int32 SectionBaseIndex = DataArray.RenderSections[j].BaseIndex;
		
		//iterate over num indices and add traingles
		for (int32 i = 0; i < SectionNumTriangles; i++)
		{
			int32 TriVertexIndex = i*3 + SectionBaseIndex;
			Tris.Add(IndicesData.Indices[TriVertexIndex]);
			Tris.Add(IndicesData.Indices[TriVertexIndex + 1]);
			Tris.Add(IndicesData.Indices[TriVertexIndex + 2]);
		}

		//Create the procedural mesh section
		ProcMeshComponent->CreateMeshSection(j, VerticesArray, Tris, Normals, UV, Colors, Tangents, true);
	}
}