Replicated

** [Drag Down] 스켈레탈 메시 병합 및 붙이기 (Skeletal Mesh Merging & Attach) ** 본문

언리얼 엔진/Drag Down

** [Drag Down] 스켈레탈 메시 병합 및 붙이기 (Skeletal Mesh Merging & Attach) **

라구넹 2025. 5. 3. 16:52

모듈러 애셋을 쓰기 위해서.. 애셋을 병합해야 한다

그런데 머리카락 같은 거 흔들린다거나 하는 이런저런 설정이 많아서 머리카락은 스켈레탈 메시 하나 더 만들어서

그냥 붙여버리는게 더 낫다고 판단된다

(흔들리지 않는 계열의 머리는 그냥 병합 처리도 가능, 흔들리는 거 포기하면 그냥 병합하면 되긴 함)

 

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "DDMeshesToMergeData.generated.h"

/**
 * 
 */
UCLASS()
class DRAGDOWN_API UDDMeshesToMergeData : public UPrimaryDataAsset
{
	GENERATED_BODY()
	
public:
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	TArray< TObjectPtr<USkeletalMesh> > MeshesToMerge;

	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	TObjectPtr<class USkeletalMesh> HairMesh;

	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	TObjectPtr<USkeleton> Skeleton;

	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	TObjectPtr<UPhysicsAsset> PhysicsAsset; 
};

최하위 데이터

병합할 메시들 메시 정보와 헤어 메시, 스켈레톤, 피직스 애셋까지 보유

 

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "DDMeshDatas.generated.h"

UENUM()
enum class EMESHID : uint32
{
	MERCC = 1
};

/**
 * 
 */
UCLASS()
class DRAGDOWN_API UDDMeshDatas : public UPrimaryDataAsset
{
	GENERATED_BODY()
	
public:
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	TMap<EMESHID, TObjectPtr<class UDDMeshesToMergeData>> Meshes;
};

그리고 하위 데이터들을 총 관리하는 데이터

enum으로 id기반해서 어떤 메시에 어떤 데이터 애셋을 연결할 건지 연결 가능

 

// Fill out your copyright notice in the Description page of Project Settings.


#include "ActorComponent/DDMeshManagerComponent.h"
#include "DataAsset/DDMeshDatas.h"
#include "DataAsset/DDMeshesToMergeData.h"
#include "SkeletalMergingLibrary.h"
#include "GameFramework/Character.h"
#include "Character/DDCharacterBase.h"
#include "DragDown.h"

UDDMeshManagerComponent::UDDMeshManagerComponent()
{
}

void UDDMeshManagerComponent::SetMergedMesh(EMESHID MeshID)
{
	if (!MeshDatas)
	{
		UE_LOG(LogDD, Warning, TEXT("No Meshes Data"));
		return;
	}
	if (!MeshDatas->Meshes.Contains(MeshID))
	{
		UE_LOG(LogDD, Warning, TEXT("Invalid MeshID"));
		return;
	}

	ACharacter* Character = Cast<ACharacter>(GetOwner());

	FSkeletalMeshMergeParams MergeParams;
	MergeParams.MeshesToMerge = MeshDatas->Meshes.Find(MeshID)->Get()->MeshesToMerge;
	MergeParams.Skeleton = MeshDatas->Meshes.Find(MeshID)->Get()->Skeleton;
	MergeParams.StripTopLODS = 0;
	MergeParams.bSkeletonBefore = true;
	MergeParams.bNeedsCpuAccess = true;

	USkeletalMesh* MergedMesh = USkeletalMergingLibrary::MergeMeshes(MergeParams);
	MergedMesh->SetPhysicsAsset(MeshDatas->Meshes.Find(MeshID)->Get()->PhysicsAsset);
	Character->GetMesh()->SetSkeletalMesh(MergedMesh);

	SetHairMesh(MeshID);
}

void UDDMeshManagerComponent::SetHairMesh(EMESHID MeshID)
{
	if (MeshDatas->Meshes.Find(MeshID)->Get()->HairMesh == nullptr)
	{
		return;
	}
	ADDCharacterBase* CharacterBase = Cast<ADDCharacterBase>(GetOwner());

	if ( CharacterBase )
	{
		CharacterBase->GetHairMeshComponent()->SetSkeletalMesh(MeshDatas->Meshes.Find(MeshID)->Get()->HairMesh);
		CharacterBase->GetHairMeshComponent()->SetMasterPoseComponent(CharacterBase->GetMesh());
	}
}

그리고 메시 병합 및 헤어 설정

 

 

헤어의 경우, 모듈러 애셋 헤어를 가져다 붙이는 거라 애초에 같은 본을 공유

소켓에 붙이면 오히려 위치 이상해지고, 그냥 하위 오브젝트로 붙이면 됨

 

메시 데이터

 

병합할 메시 데이터

 

완벽하게 병합이 되었다!