728x90
이 글은 Inflearn - Rookiss : 언리얼 엔진4 입문 강의를 듣고 정리한 글입니다.

 

목차.

  1. 서론
  2. 소켓이란?
  3. 소켓 추가
  4. C++ 클래스에서 무기 추가
  5. 액터로 코드 수정
  6. 결론

 

서론

 

언리얼 엔진에서 Skeletal Mesh와 Socket를 활용하면 플레이어가 무기를 자연스럽게 쥐도록 구현할 수 있습니다.

이 글에서는 Skeletal Mesh Socket를 사용하여 플레이어 손에 무기를 쥐어주는 방법에 대해 알아보겠습니다.

 

소켓이란?

 

먼저, Skeletal Mesh와 소켓(Socket)이 무엇인지 이해해야 합니다. Skeletal Mesh는 캐릭터 또는 오브젝트의 빼대 와 함께 애니메이션을 할 수 있는 모델을 나타냅니다. Socket는 이 Skeletal Mesh의 특정 부분에 무기 또는 다른 아이템을 부착할 수 있는 지점을 의미합니다.

 

플레이어가 다양한 무기를 사용하거나, 옷을 갈아입거나 할 때 소켓을 이용해서 간단하게 변경이 가능합니다.

 

소켓 추가

 

무기를 쥐어주려는 Skeletal Mesh에 Socket을 생성해야 합니다.

 

사용 중인 블루프린트 클래스에서 Mesh 컴포넌트를 눌러보면 Skeletal Mesh가 보입니다.

 

Skeletal-Mesh
Skeletal Mesh

 

선택하고 편집 창으로 들어갑니다.

좌측 스켈레톤 트리에 보면 root 하위에 많은 계층구조를 볼 수 있습니다.

 

스켈레톤-트리
스켈레톤 트리

 

무기를 쥐어주려는 위치에 소켓을 추가해 주면 됩니다.

보통 hand_l과 같이 검색을 하면 바로 손을 찾을 수 있습니다. 

hand_l에 마우스 우클릭 -> 소켓 추가를 하면 hand_l 하위에 소켓이 하나 생성됩니다.

 

소켓-추가
소켓-추가

 

소켓을 임의로 사용해 보기 위해 칼을 한번 추가해 보겠습니다.

생성된 소켓을 우클릭해 보면 프리뷰 에셋 추가 항목이 있습니다.

여기서 원하는 무기를 선택해 줍니다.

 

위치와 회전을 조정하여 소켓에 자연스럽게 부착되도록 합니다.

 

socket에-무기를-장착
socket에 무기를 장착한 모습

 

이대로 게임 실행을 하더라도 손에 추가한 무기가 적용되어있지 않습니다.

C++ 클래스에 코드를 작성해서 Socket에 칼을 생성하도록 해주겠습니다.

 

C++ 클래스에서 무기 추가

 

MyCharacter.h

public:
....
    UPROPERTY(VisibleAnywhere)
    UStaticMeshComponent* Weapon;

 

MyCharacter.cpp

// Sets default values
AMyCharacter::AMyCharacter()
{
....
	FName WeaponSocket(TEXT("hand_l_socket"));
	if (GetMesh()->DoesSocketExist(WeaponSocket))
	{
		Weapon = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WEAPON"));

		static ConstructorHelpers::FObjectFinder<UStaticMesh> SW(TEXT("StaticMesh'/Game/ParagonGreystone/FX/Meshes/Heroes/Greystone/SM_Greystone_Blade_01.SM_Greystone_Blade_01'"));
		if (SW.Succeeded())
		{
			Weapon->SetStaticMesh(SW.Object);
		}
		Weapon->SetupAttachment(GetMesh(), WeaponSocket);
	}
}

 

지금까지 Mesh를 추가했던 코드들과 별로 다른 점은 없습니다.

DoesSocketExist를 통해 내가 만든 소켓이 메쉬에 있는지 확인을 하고

있다면 Weapon에 WEAPON이라는 StaticMesh 컴포넌트를 추가, 그리고 경로를 지정해서 원하는 매쉬를 불러오도록 해줬습니다.

 

무기를-장착
무기를 잘 장착한 모습

 

컴파일 후 실행해 보면 손에 잘 생성된 것을 볼 수 있습니다.

 

액터로 코드 수정

 

위와 같이 Mesh를 바로 붙이는 식으로 코드를 작성해도 되지만 바닥에 무기를 스폰해서

플레이어가 장착해야한다면 문제가 있을 것입니다.

 

무기를 액터로 만들어서 바닥에 배치하고 플레이어에게 붙이는 방법으로 구현하겠습니다.

 

Actor로 클래스를 추가해 줍니다.

 

Actor-클래스-생성
Actor 클래스 부모로 생성

 

 스폰되어있는 무기에 Tick함수는 필요 없기 때문에 Tick 함수를 지워주고 
PrimaryActorTick.bCanEverTick 도 false로 해주었습니다.

 

MyWeapon.h

public:
	UPROPERTY(VisibleAnywhere)
	UStaticMeshComponent* Weapon;

 

MyWeapon.cpp

#include "MyWeapon.h"

AMyWeapon::AMyWeapon()
{
	PrimaryActorTick.bCanEverTick = false;
	Weapon = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WEAPON"));

	static ConstructorHelpers::FObjectFinder<UStaticMesh> SW(TEXT("StaticMesh'/Game/ParagonGreystone/FX/Meshes/Heroes/Greystone/SM_Greystone_Blade_01.SM_Greystone_Blade_01'"));
	if (SW.Succeeded())
	{
		Weapon->SetStaticMesh(SW.Object);
	}
	Weapon->SetCollisionProfileName(TEXT("NoCollision"));
}

 

SetCollisionProfileName을 NoCollision으로 설정해 주었습니다.

 

이제 스폰을 구현하겠습니다

 

MyCharacter.cpp

void AMyCharacter::BeginPlay()
{
	Super::BeginPlay();

	FName WeaponSocket(TEXT("hand_l_socket"));

	auto CurrentWeapon=GetWorld()->SpawnActor<AMyWeapon>(FVector::ZeroVector, FRotator::ZeroRotator);

	if (CurrentWeapon)
	{
		CurrentWeapon->AttachToComponent(GetMesh(),
			FAttachmentTransformRules::SnapToTargetNotIncludingScale,
			WeaponSocket);
	}
}

 

GetWorld()에 많은 게임 기능들이 있는데 그중 Actor를 스폰하는 기능도 있습니다.

매개변수로 일단 위치와 회전을 모두 0으로 해주었고

 

AttachToComponent를 통해 소켓에다 새로 스폰한 엑터를 붙여줄 수 있게 됩니다.

 

결론

 

지금까지 스켈레탈 매쉬(Skeletal Mesh)에 소켓(Socket)을 추가하고

C++ 클래스를 이용해 소켓에 무기를 장착시켜 주는 코드를 작성했습니다.

그리고 액터 클래스를 작성해서 바닥에 무기를 스폰하는 코드를 작성해 봤습니다.

 

728x90

+ Recent posts