Content and Documentation for Customizable characters using FSkeletalMeshMerge

I find merging meshes to be way better than a modular pawn because the shadow outlines arent separate like they are when having multiple SkeletalMeshComponents, and its probably much more performant (other than at load time when the merging occurs) because there’s only one SkeletalMesh being animated/rendered (I don’t know what they are talking about texture atlases and stuff, you can have multiple materials per SkeletalMesh !)

Here’s the code for a component which has an editable SketetalMesh piece list (in the editor), and generates the mergemesh on creation time:
.h :


#pragma once

#include "CompositeModelComponent.generated.h"

/** Component that contains multiple SkeletalMeshes as a single unit */
UCLASS(editinlinenew, meta=(BlueprintSpawnableComponent), ClassGroup=Rendering)
class UCompositeModelComponent : public USkeletalMeshComponent
{
	GENERATED_UCLASS_BODY()
private:
	UPROPERTY(EditAnywhere, Category = "Pieces")
	TArray<USkeletalMesh*> PieceMeshes;

	void OnRegister() override;
	void OnUnregister() override;

	void CreatePieceComponents();
};


.cpp:



#include "CompositeModelComponent.h"

//////////////////////////////////////////////////////////////////////////

UCompositeModelComponent::UCompositeModelComponent( const FPostConstructInitializeProperties& PCIP )
	: Super( PCIP )
{
	PrimaryComponentTick.bCanEverTick = true;

	SetCollisionProfileName(UCollisionProfile::BlockAllDynamic_ProfileName);
}


void UCompositeModelComponent::CreatePieceComponents()
{
	if (GetOwner() == nullptr)
		return;

	if (PieceMeshes.Num() > 0)
	{
		TArray<USkeletalMesh*> mergeMeshes;
		mergeMeshes.Empty(PieceMeshes.Num());

		for (int32 i=0; i<PieceMeshes.Num(); i++)
		{
			if (PieceMeshes* == nullptr)
				continue;

			mergeMeshes.Add(PieceMeshes*);
		}

		if (mergeMeshes.Num() > 0)
		{
			USkeletalMesh* targetMesh = ConstructObject<USkeletalMesh>(USkeletalMesh::StaticClass(),this,FName("MergedMesh"),RF_Transient);
			TArray<FSkelMeshMergeSectionMapping> sectionMappings;
			FSkeletalMeshMerge merger(targetMesh,mergeMeshes,sectionMappings,0);
			const bool mergeStatus = merger.DoMerge();
			check(mergeStatus == true);

			this->SetSkeletalMesh(targetMesh);
		}		
	}
}

void UCompositeModelComponent::OnRegister()
{
	CreatePieceComponents();
	Super::OnRegister();
}

void UCompositeModelComponent::OnUnregister()
{
	Super::OnUnregister();
}


Please note, that the FSkeletalMeshMerge thing supplied with UE4 identifies materials on the input meshes by their UMaterial*, so make sure you have a default material properly set on all the source SkeletalMeshes, otherwise the output MergedMesh will be all the same material (as all input UMaterial* are nullptr). I think this is a bug and should be fixed (it should identify by source material ids, increasing for each source piece, this would make the output material list in a predictable order as well).