목차
- 소켓을 추가하기
- c++로 무장 및 해제하기
1. 소켓을 추가하여 실제로 무장 해제하기
무기를 해제해서 등 뒤로 옮기려고 한다. 그러기 위해서 캐릭터의 스켈레톤매시에 새로운 소켓을 추가하여야 한다.
캐릭터의 스켈레톤 매시에서 검을 놓기 적절한 위치를 찾아 소켓을 추가해준다.
우클릭하여 소켓을 추가해주자.
프리뷰 에셋을 추가하여 검의 위치를 잡아보자.
대략 이런 형태로 옮기고 제대로 됐는지 확인하기 위해 우측의 프리뷰 신에서 애니메이션 미리보기를 해본다.
이런식으로 애니메이션을 재생시켜 검의 위치를 잡을 수 있다. 이때 너무 정확하게 맞출 필요는 없으며 대략 비슷하게만 맞추면 된다.
이제 실제로 검을 장착하거나 장착해제해 보자.
2. c++로 무장 및 해제하기
무장을 하거나 무장을 해제하는 그 시점에 노티파이를 추가해준다.
이제 노티파이가 있으니 실제로 무장을 해제하거나 무장을 해보자. 비주얼 스튜디오로 돌아간다.
void AWeapons::Equip(USceneComponent* InParent, FName InSocketName)
{
FAttachmentTransformRules TransformRules(EAttachmentRule::SnapToTarget, true);
ItemMesh->AttachToComponent(InParent, TransformRules, InSocketName);
}
우리가 맨 처음 장비를 장착하려고 작성한 이 구문을 이용해서 무장 및 무장해제를 할 수 있을 것이다.
함수 기능을 다시한번 살펴보자
FAttachmentTransformRules : 두 컴포넌트를 어떻게 부착시킬지 설정하는 구조체이다.
EAttachmentRule::SnapToTarget : ItemMesh의 위치, 회전, 크기를 InParent의 소켓 위치와 동일하게 맞춘다는 규칙을 설정한다.
여기서 ItemMesh는 무기, InParent는 캐릭터이다.
ItemMesh->AttachToComponent(InParent, TransformRules, InSocketName);
InParent: ItemMesh를 부착할 컴포넌트이다.
TransformRules : 위에서 설정한 부착 규칙이다.
InSocketName : ItemMesh를 부착할 InParent의 소켓 이름이다.
위의 함수는 지금 퍼블릭 공간에 있으므로 캐릭터 클래스에서도 사용할 수 있다.
캐릭터 헤더파일로 돌아가 노티파이와 연결될 함수를 만들자.
UFUNCTION(BlueprintCallable)
void Disarm();
void AKnight::Disarm()
{
if (EquippedWeapon)
{
EquippedWeapon->AttachMeshToSocket(GetMesh(), FName("SpineSocket"));
}
}
// AttachMeshToSocket 은 Equip 함수의 이름만 바뀐 것이고 내용은 똑같다.
노티파이로 해당 함수를 호출하여 무장해제를 할 것이다.
캐릭터 애니메이션 블루프린트로 들어가 다음과 같이 연결하자. 다음과 같이 하면 무기를 등 뒤로 옮길 수 있다.
물론 아직 완벽한 것은 아니라 문제점이 많다. 무기가 없어도 애니메이션이 작동하고 한번 무장해제를 하면 다시는 무장을 할 수 없다. 이 부분들을 수정해보자.
적절한 시점에 Arm 노티파이를 추가하자.
이제 c++ 에서 무장할때 호출할 함수를 만들자.
// 헤더파일
UFUNCTION(BlueprintCallable)
void Arm();
// C++ 파일
void AKnight::Arm()
{
if (EquippedWeapon)
{
EquippedWeapon->AttachMeshToSocket(GetMesh(), FName("RightHandSocket"));
}
}
Disamr 함수와 유일한 차이점은 무기가 장착될 소켓이다.
컴파일하고 애니메이션 블루프린트에서 노티파이랑 이 함수를 연결하자.
이제 무장과 무장해제가 잘 되는 것을 볼 수 있다. 현재 또 다른 문제로는 무장 애니메이션 중 이동이 가능하다. 이부분을 막아보려고 한다.
UENUM(BlueprintType)
enum class EActionState : uint8
{
EAS_Unoccupied UMETA(DisplayName = "Unoccoupied"),
EAS_Attacking UMETA(DisplayName = "Attacking"),
EAS_EquippingWeapon UMETA(DisplayName = "EquippingWeapon") // 해당부분 추가
};
캐릭터 스테이트 열거형에서 무장중이라는 부분을 추가해준다.
void AKnight::EKeyPressed()
{
AWeapons* OverlappingWeapon = Cast<AWeapons>(OverlappingItem);
if (OverlappingWeapon)
{
OverlappingWeapon->Equip(GetMesh(), FName("RightHandSocket"));
CharacterState = ECharacterState::ECS_EquippedOneHandWeapon;
OverlappingItem = nullptr;
EquippedWeapon = OverlappingWeapon;
}
else if (CanDisarm())
{
PlayEquipMontage(FName("Unequip"));
CharacterState = ECharacterState::ECS_Unequipped;
ActionState = EActionState::EAS_EquippingWeapon; // 해당 부분 추가
}
else if (CanArm())
{
PlayEquipMontage(FName("Equip"));
CharacterState = ECharacterState::ECS_EquippedOneHandWeapon;
ActionState = EActionState::EAS_EquippingWeapon; // 해당 부분 추가
}
}
이제 무장을 하는 부분에 액션 스테이트를 변경하자.
void AKnight::Move(const FInputActionValue& Value)
{
if (ActionState != EActionState::EAS_Unoccupied) return;
// 이하 생략
이제 이동하는 함수에서 비점거 상태가 아니면 리턴을 하도록 할 수 있다.
이제 무장 및 무장해제를 완료하면 다시 원래의 상태로 만들 필요가 있다. 노티파이를 추가하고 캐릭터 애니메이션 블루프린트에서 이를 수정해보자.
적절한 시점에 노티파이를 추가해준다.
캐릭터 애니메이션 블루프린트에서 다음과 같이 설정하면 되는데, Finish Equipping은 c++에서 만든 액션스테이트를 바꾸는 함수로 c++에서 만들지 않고 그냥 블루프린트에서 set actionstate로 액션스테이트의 상태를 바꿔도 성능상 차이는 없어서 둘 중 편한 것으로 하면 된다.
이렇게 해서 캐릭터 캐릭터의 무장 및 무장해제를 구현하였다.
'게임프로그래밍 > 실습1' 카테고리의 다른 글
[언리얼 실습] 23. 무기 히트를 위한 콜리전 박스 추가랑 트레이싱 추가하기 (1) | 2024.10.27 |
---|---|
[언리얼 실습] 22. C++에서 아이템 습득시 사운드 재생하기 (0) | 2024.10.27 |
[언리얼 실습] 20. 무장 해제 애니메이션 적용 (0) | 2024.10.26 |
[언리얼 실습] 19. 메타사운드를 활용하여 랜덤사운드 재생하기 (0) | 2024.10.26 |
[언리얼 실습] 18. 메타사운드를 활용하여 효과음 추가 (0) | 2024.10.26 |