🎮Unreal4/C++_TPS

[UE4] 1인칭 모드(FPS-AK47) : Arms Mesh, 3인칭↔1인칭 변환

공대 컴린이 2023. 3. 17. 18:18
728x90

👧🏻 1인칭 모드 - AK47

앞서 AR4 소총을 구현할때는  3인칭으로 Idle 모션과 Aim 모션을 구현하였다.

이번에는 AK47 소총 무기를 새롭게 추가하면서 소총에 조준경을 추가하여, Aim 상태에서는 조준경을 확대하여 보는 1인칭 시점을 구현해보았다.

1️⃣ 1인칭 캐릭터 Mesh 가져오기

 

먼저, 1인칭 모드를 구현하기 위해선 카메라를 캐릭터의 얼굴 위치에 놓고 양팔만 나오는 1인칭용 캐릭터 Mesh를 적용해야 한다. 나는 언리얼의 1인칭 블루프린트 피처를 다운받아 해당 에셋 안에 포함된 캐릭터 Mesh를 가져와 사용했다.

팔만 있는 SkeletalMesh와 Idle 애니메이션 두가지를 우선 가져와서 구현하였다.

2️⃣ Player 클래스에 Arms Mesh 추가하기

Player 클래스

가져온 Arms Mesh를 Player 컴포넌트에 추가하기 위해 SkeletalMeshComponent를 생성한 뒤, 초기화 해 주었다.

 

Player - 생성자

Arms 메시를 카메라에 붙이고나서, 화면에 보이는 손의 위치를 알맞게 조정하여 Location과 Rotator를 변경하였다.

이후 기본적인 캐릭터는 3인칭이기 때문에 Arms의 SetVisibility는 false로 설정하였다.

3️⃣ Arms Anim Instance 만들기

Arms의 애니메이션을 구현하기 위해 Arms 애니메이션 블루프린트를 생성하였다.

 

이후, 기본동작인 AnimRifle을 재생함으로써 Arms의 메시가 Idle 애니메이션을 수행하게 되었다.

(우선 1인칭 모드를 구현하기 위해 Weapon Type 블렌드포즈의 디폴트를 임시로 지정해놓은 것이다.)

 

Player - 생성자

Arms 애니메이션 블루프린트를 만들때 사용한 Arms Anim Instance를 생성하여 Arms의 AnimClass로 설정해주었다.

 

Arms의 AnimInstance는 3인칭인 Character의 AnimInstance와 거의 동일하게 작성되었다.

 

Player의 뷰포트에서 보면 3인칭 Character와 1인칭 Arms가 위와 같이 배치되어 사용된다.

게임 속에서는 두 개의 메시 중 하나의 메시만 Visible을 활성화하여 사용할 것이다.

4️⃣ 3인칭 모드(Idle)와 1인칭 모드(Aim) 사이의 전환 구현하기

Weapon 클래스

1인칭 모드는 AK47 무기를 들고 Aim 모드에 들어갔을 때만 실행시키기 위해서 AK47의 Begin_Aim, End_Aim 함수에서 작동시켜야 한다. 따라서 모든 무기의 부모 클래스인 Weapon 클래스의 Begin_Aim, End_Aim 함수를 virtual 키워드로 추상화하였고, AK47에서 오버라이드 해주었다.

 

Aim 모드가 시작될 때 조준점을 보이지않도록 Hidden 설정하고, 3인칭 캐릭터인 Owner->GetMesh의 Visibility는 비활성화하였다. 또한 3인칭 캐릭터에 붙은 Backpack 또한 비활성화하고, 1인칭 Arms를 활성화시켜주었다.

이후 3인칭 캐릭터의 오른손에 붙어있던 총을 1인칭 Arms의 오른손으로 옮겨야하기 때문에 Attach To 함수를 이용하여 Owner->GetArms로 변경해주었다.

 

End Aim 함수에서는 Begin Aim과 반대로 설정하면 된다.

숨겨놨던 조준점을 활성화하고, 마찬가지로 3인칭 캐릭터와 백팩을 활성화한다. 반대로 1인칭 Arms는 비활성화한 뒤, 1인칭의 Arms에 붙은 총을 다시 3인칭 캐릭터(Owner->GetMesh())의 오른손으로 옮겨온다.

5️⃣ 3인칭↔1인칭 변환 시 무기를 관리하는 델리게이트

Begin_Aim 함수와 End_Aim 함수의 마지막에 붙은 델리게이트는 3인칭↔1인칭 변환시에 다른 무기들의 활성화를 관리하기 위해 생성하였다.

 

먼저, 델리게이트를 생성하기 전 1인칭 화면은 위와 같다.

1인칭 모드로 들어갔지만 3인칭 캐릭터만 비활성화되고, 캐릭터에 붙은 무기들은 비활성화되지 않아서 1인칭 시야에 다른 무기가 걸리게된다.

 

따라서 1인칭 모드로 들어갔을 때 현재 사용중인 무기 이외의 다른 무기들은 비활성화시켜야 하는데, AK47 클래스에서 WeaponComponent에 직접 접근하여 등록된 다른 무기들을 제어하는것은 부모(WeaponComponent-Weapon) - 자식(AK47)간의 순환참조이기 때문에 이러한 구조는 지양해야한다.

 

따라서 WeaponComponent에서 델리게이트를 생성하여 Aim모드의 Begin과 End 시에 호출되도록 만들고 Aim모드의 Begin시에 AK47에서 자기자신(AK47 Weapon객체)를 보내어 WeaponComponent에서 매개변수로 받은 Weapon 제외에 나머지 무기를 비활성화시키면 된다.

 

따라서 위와 같은 FWeaponAim_Arms_Begin FWeaponAim_Arms_End 이름의 델리게이트를 각각 생성하고 Begin 델리게이트에는 ACWeapon* 을 매개변수로 하나 받는다.

 

WeaponComponent의 BeginPlay에서 델리게이트에 함수들을 등록해주었고,

 

각각 등록한 함수 내용을 구현해주었다.

On_Begin_Aim은 위에서 설명한대로 매개변수로 받은 무기를 제외한 나머지를 전부 비활성화시키고, On_Begin_End 함수는 모든 무기의 비활성화를 해제하는 것이다.

 

이렇게 만들어진 델리게이트를 AK47 클래스의 Begin_Aim, End_Aim 함수에서 각각 호출하였다.

 

아래는 성공적으로 구현된 3인칭과 1인칭의 게임 플레이 사진이다.

3인칭 (Idle 모드) 1인칭 (Aim 모드)
3인칭 (Idle 모드) 1인칭 (Aim 모드)
728x90