게임에 따라 맨손으로 시작했다가 무기를 교체하며 들고 있을 수 있다.

그것을 구현하는 실습이다.

 

우선은 만들어둔 소켓을 C++ 클래스에서 직접 메시를 붙여주는것부터 시작하자.

 

 

스켈레톤 트리에서 왼손에 소켓을 추가해준다.

해당 소켓에서 우클릭 시, 프리뷰 애셋이란것을 추가해 줄 수 있는데 실제로 적용되는것은 아니고 말 그대로 위치를 잡아주기 위해 프리뷰 애셋을 하나 가져와서 작업하기 편하게 하는 것이다. 소켓의 위치를 조정해주면 된다.

 

// MyCharacter.h
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* Weapon;

// MyCharacter.cpp
AMyCharacter::AMyCharacter()
{
	// .. 생략
    FName WeaponSocket(TEXT("hand_l_socket"));
    if (GetMesh()->DoesSocketExist(WeaponSocket)) // hand_l_socket이 있는가?
    {
        // 있으면 메시 컴포넌트 생성
        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);
    }
}

 

 

무기도 하나의 액터로 만들어서 소켓에 붙이는 방식을 사용할 수 있다.

 

 

// MyWeapon.h
class TESTUNREALENGINE_API AMyWeapon : public AActor
{
public:
    UPROPERTY(VisibleAnywhere)
    UStaticMeshComponent* Weapon;
};

// MyWeapon.cpp
AMyWeapon::AMyWeapon()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = false; // 무기는 Tick이 필요없다

    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);
    }

    // 충돌까지도 설정하고 싶다면 콜리전 프리셋 설정. 현재는 NoCollision으로 설정
    Weapon->SetCollisionProfileName(TEXT("NoCollision"));
}

// MyCharacter.cpp
void AMyCharacter::BeginPlay()
{
    Super::BeginPlay();

    FName WeaponSocket(TEXT("hand_l_socket"));

	// 유니티의 Instantiate와 비슷한 기능
    auto CurrentWeapon = GetWorld()->SpawnActor<AMyWeapon>(FVector::ZeroVector, FRotator::ZeroRotator);

    if (CurrentWeapon)
    {
        // 위의 WeaponSocket에다가 SpawnActor로 만든 CurrentWeapon을 붙여준다
        CurrentWeapon->AttachToComponent(GetMesh(),
            FAttachmentTransformRules::SnapToTargetNotIncludingScale,
            WeaponSocket);
    }
}

 

MyCharacter의 생성자에서 소켓에 붙여주던 코드는 삭제하고 MyWeapon의 생성자와 MyCharacer의 Begin으로 코드를 분산시켰다.

 

AttachToComponent 코드를 삭제한다면 소켓에 붙지 않고 맵 중앙에 칼이 스폰된 상태 그대로 있게된다.

 

GetWorld 메소드는 전역으로 굉장히 많은 기능들을 들고있다.

소켓은 언리얼과 유니티 모두에 존재하는 개념이다.

+ Recent posts