Skeletal Mesh Socket을 이용해서 캐릭터에 무기를 장착해보자
1. Skeletal Mesh Socket 이란?
- 게임에서 캐릭터 본에 오브젝트를 붙이는 경우에 사용
- Skeleton에서 원하는 위치에 Socket을 생성한 다음 그 Socket 위치에 오브젝트를 생성할 수 있다.
자세한 내용은 공식 문서에서!!
2. Socket을 붙여보자
캐릭터의
Skeleton
을 연 다음Skeleton Tree
에서 원하는 위치에Socket
을 장착해보자.
2-1. 원하는 본 위치에서 우클릭을 통해 Socket
을 생성할 수 있다. (Add Socket)
오른손에 무기를 장착시킬 것이기 때문에 RightHand
본에 추가해주었다.
2-2. Socket에서 우클릭 시, Add preview Asset
이 있는데 이걸 통해 임시로 객체를 넣어볼 수 있다.
2-3. 임시로 객체를 넣은 후, 원하는 방향 및 각도를 조절한다.
2-4. Preview Animation 이용해서 Socket의 방향, 각도에 디테일을 살리자
3. C++ 코드를 통해 장착하자!
무기의 정보를 가지고 있는 Weapon 이란 이름의 (Actor를 부모로 한)클래스를 생성하였습니다.
3-1. 변수 생성
- 무기 객체를 받아올 수 있게 변수를 생성했다.
1 2
UPROPERTY(EditAnywhere,Category="Combat System",meta=(AllowPrivateAccess="true")) TSubclassOf<class AWeapon> Sword;
TSubclassOf 이란?
공식 문서에 설명이 너무 잘 나와 있어 공식 문서 내용을 가져왔습니다.
TSubclassOf 는 UClass 유형의 안전성을 보장해 주는 템플릿 클래스입니다.
예를 들어
디자이너가 대미지 유형을 지정하도록 해주는 프로젝타일 클래스를 제작중이라 가정합시다.
그냥 UPROPERTY 유형의 UClass 를 만든 다음
디자이너가 항상 UDamageType 파생 클래스만 할당하기를 바라거나,
TSubclassOf 템플릿을 사용하여 선택지를 제한시킬 수도 있습니다. 그 차이점은 아래 코드와 같습니다:
- 아래와 같은 선언에서는 아무 UClass 나 선택할 수 있습니다.
```cpp /** type of damage / UPROPERTY(EditDefaultsOnly, Category=Damage) UClass DamageType;
1
2
3
4
5
- 아래와 같이 템플릿 클래스는 에디터의 프로퍼티 창에 **UDamageType 파생 클래스만 선택되도록 합니다**.
```cpp
/** type of damage */
UPROPERTY(EditDefaultsOnly, Category=Damage)
TSubclassOf<UDamageType> DamageType;
3-2. Weapon을 세팅하는 메소드 구현
- 선언
1 2
UFUNCTION() void AttachWeapon(TSubclassOf<AWeapon> Weapon) const;
- 정의
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
void APlayerCharacter::AttachWeapon(TSubclassOf<AWeapon> Weapon) const { if(Weapon) { // Weapon에는 무기 정보만 담겨 있고, 실제 객체는 생성되어 있지 않기 때문에 SpawnActor를 통해 객체를 생성했다. AActor* SpawnWeapon = GetWorld()->SpawnActor<AWeapon>(Weapon); // 위에서 생성한 Socket 이름을 통해 Socket 정보를 가져온다. const USkeletalMeshSocket* WeaponSocket = GetMesh()->GetSocketByName("RightHandWeaponSocket"); if(WeaponSocket && SpawnWeapon) { // 가져온 Socket에 Actor를 붙인다. WeaponSocket->AttachActor(SpawnWeapon,GetMesh()); } } }
- 호출
1 2 3 4 5 6 7
// Called when the game starts or when spawned void APlayerCharacter::BeginPlay() { Super::BeginPlay(); AttachWeapon(Sword); }
4. 결과
- 게임 실행 시, 무기가 소켓 위치에 생성되어 정상적으로 작동되는 것을 볼 수 있다.
- 위 내용을 토대로, 인벤토리에서 무기를 꺼내 장착하거나, 무기를 주워 장착하거나 등 다양한 액션을 구현해볼 수 있다.