Post List

2017/11/29

Unreal4__2_무기붙이기_활쏘기

스켈레톤 특정 본에 무기 붙이기와 애니메이션 특정 시점에 화살을 생성해서 발사하는 부분까지 만들어 보았습니다.

아래 Gif를 보시면 플레이어가 화살을 쏘는 애니메이션이 플레이 되면서 활을 당기기전 화살이 생성되고 , 발사되는 시점에 화살이 앞으로 나아가는 모습을 볼수있습니다.
[ 무기 붙이기 ]
우선 왼쪽 손에 활을 붙여보겠습니다.
스켈레톤이나 애니메이션 브라우저를 열면 왼쪽에 스켈레톤 트리가 나옵니다! 여기서 이제 무기를 붙여줄 본을 찾으시면 됩니다.

저는 'middle_02_l' 본에 붙여보도록 하겠습니다.

'middle02_l' 본을 우클릭하여 소켓을 추가해줍니다. 추가한 소켓을 'WeaponPoint'라고 이름을 지어주었습니다. 
(여기서 사용된 소켓이름은 c++이나 블루프린트에서 사용되니! 잘 기억하고 있으시면 좋겠죠?)

여기서 프리뷰를 사용하면 내가 붙이고자 하는 무기를 소켓위치에 직접 붙여볼 수 도 있습니다. 그리고 소켓의 위치와 회전값을 
무기에 맞게 변경해주면 플레이어가 실제 활을 들고있는것 처럼 보여지게 됩니다. 
애니메이션을 플레이 해보면서 확인도 가능하답니다.

이와 같은 방법으로 화살은 오른손 본에 소켓을 추가하여 작업을 해주었습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void AJPlayer::BeginPlay()
{

    // 이 엑터가 레벨에 정상적으로 스폰되었을 때 호출되는 함수.
    Super::BeginPlay();
    FActorSpawnParameters SpawnInfo;
    // 활 메시를 생성한다.
    m_pWeaponMesh = GetWorld()->SpawnActor<AJBow>(SpawnInfo);
    if (m_pWeaponMesh != nullptr)
    {
        m_pWeaponMesh->SetOwningPawn(this);
        m_pWeaponMesh->OnEquip();
    }
cs

C++ 코드를 보면 플레이어의 BeginPlay()함수에서 무기를 붙여주는 코드입니다.
AJBow는 AJWeapon을 상속받는 무기 클래스이며, 활 메시를 가지고 있답니다.

!. 잠시 무기 클래스들의 관계를 살펴보겠습니다.
AActor를 상속받는 JWeapon 클래스는 무기의 상위 클래스로 공통적으로 가져야할 변수나 기능들이 구현되어있으며, 이를 상속받은 JArrow나 JBow 클래스는 메쉬, 콜리젼, 충돌 판정, 장착 및 해제 등 기본적인 기능들은 부모의 데이터를 가져다 사용하게 됩니다. 
화살의 경우 캐릭터 메쉬에 Attach되어있다 발사될 시점에 Detach된 후 해당 방향으로 이동되어야 하는 특징이 모든 클래스마다 구현되어있으면, 낭비와 클래스의 용도에 대해 모호성이 발생하겠지요.
그래서 무기의 쓰임에 따라 저는 클래스로 구분하였답니다.

다시 본론으로 넘어와서! 무기가 정상적으로 스폰이 되면 무기(actor)에 소유자인 플레이어(pawn)를 인자로 넘겨줍니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void AJWeapon::AttachMeshToPawn()
{
    if (m_pPawn != nullptr)
    {
        USkeletalMeshComponent* pPawn = m_pPawn->GetSpecificPawnMesh();
        FName strAttachName = m_pPawn->GetWeaponAttachPointName();
        m_pMesh->AttachTo(pPawn, strAttachName);
    }
}
void AJWeapon::OnEquip()
{
    AttachMeshToPawn();
}
cs

OnEquip() 함수는 레벨에 생성된 무기를 이제 pawn 메시에 붙이기 위한 함수로,
AttachMeshToPawn()함수를 호출하게 됩니다현재는 단순히 붙이는 기능을 구현했기때문에 매우 간단하답니다..

AttachMeshToPawn()함수를 보면 m_pPawn AJPlayer 객체로 BeginPlay()에서 AJBow를 스폰했을 때 m_pWeaponMesh->SetOwningPawn(this);
인자로 전달한 this는 AJPlayer 객체, 즉 무기를 스폰한 폰의 주소값이지요.

이제  m_pPawn 이용해 어떤 메시에 붙일 것인지또한 어떤 소켓에 붙일것인지에 대한 정보를 가져오게 됩니다.
아까 위에서 추가한 'WeaponPoint' 소켓을 여기서 사용하게 됩니다.

AttachTo()함수의 인자값으로 소켓을 추가했던 스켈레톤메시와 소켓의 이름을 전달함으로써무기는 AJPlayer 왼쪽 손에 붙게 됩니다!


[ 화살 발사하기 ]
무기를 붙여보았으니 이번에는 화살을 쏘아보겠습니다.

우선 저는  'Q' 키를 눌렀을  활을 쏘는 애니와 화살(actor) 레벨로 스폰하기 위해
키바인딩 작업을 먼저 진행했습니다. ( 키바인딩에 대한 자세한 내용은 생략하겠습니다! )

우선 키(Q)를 입력했을  공격 애니메이션을 플레이하기 위해 C++에서의 데이터를 블루프린트에서 읽어올  있도록 확장을 했습니다.

1
2
3
    UFUNCTION(BlueprintCallable, Category = "Joy | State")
        bool IsFire() const;
cs
C++ 메소드를 블루프린트로 확장하기 위해서는 언리얼에서 제공되는 메크로(UFUNCTION) 사용하시면 쉽게 접근하실  있습니다.

 사진처럼 애니메이션 블루프린트의 이벤트 그래프에서 JPlayer IsFire()함수를 호출할  있습니다.
(여기서 IsFire함수는 JPlayer 멤버함수이므로 형변환이 우선적으로 필요하겠지요?!)

약간 혼동이   있는데 이벤트 그래프의 Set Is Firing 노드는 애니메이션 블루프린트에서 추가해준 변수입니다.
c++에서 IsFire() 함수의 반환 값을 받아와 애니메이션 블루프린트 변수에 값을 넣어주는 것이지요.

isFiring 변수가 이벤트 그래프에서 true값으로 변경이 되면 애니메이션 그래프에서 idle -> fire 상태로 이동하게 됩니다.
idle -> fire로 전환되는 조건 체크가 isFiring 변수가 true 일때이기 때문이죠.

이제 Q를 눌렀을 때 활을 쏘는 애니메이션이 나오는것 까지 완성되었습니다.

그 다음은 Q를 눌렀을 때 바로 화살이 발사될 수 있도록 만들어 볼텐데요, 여기서 'Q'를 누르자 마자 화살이 나가는게 아니라 애니메이션 모션에 맞춰 발사해보도록 해보겠습니다.

공격 애니메이션을 열어보면 노티파이라는 부분이 있습니다.
이 부분은 특정 애니메이션 시점에 이벤트를 시킬 수 있는 기능인데요. 저는 커스텀 노티파이를 이용하여 화살이 발사되는 시점을 C++로 알려주는 작업을 해보겠습니다.

노티파이에 커스텀 노티파이를 생성하여 이름을 'shoot' 으로 해주었습니다. 이제 이 shoot 노티파이를 가지고 C++에서 실제 플레이어가 바라보는 방향으로 화살을 발사시키는 함수를 호출시키도록 해보겠습니다.

1
2
3
4
5
6
7
    // JPlayer.h
    UFUNCTION(BlueprintCallable, Category = "Joy | State")
        void Shoot();
    UFUNCTION(BlueprintCallable, Category = "Joy | State")
        void EndShoot();
cs
C++함수를 블루프린트에서 호출될 수 있도록 UFUNCTION 메크로로 함수를 확장 시켜줍니다.
Shoot()은 화살을 발사시키는 함수이고, Shoot_End()는 애니메이션의 종료를 알리는 함수 입니다.

노티파이와 C++ 함수를 추가하고 다시 애니메이션 블루프린트의 이벤트 그래프로 오면 
위와 같은 노드를 생성할 수 있습니다.
Shoot() 과 End_Shoot()은 JPlayer의 멤버함수 이므로 이 또한 형변환이 되어야 호출할 수 있습니다.
Shoot 노티파이와 Shoot_End 노티파이를 각각 연결해주면 
해당 애니메이션에서 추가한 노티파이 프레임에 도달했을 경우 이벤트 그래프에서 연결된 함수들이 호출됩니다.

그러면 Shoot 함수에서는 플레이어의 오른손에 붙어있던 화살을 분리한 다음 플레이어가 바라보는 방향으로 날라가게된답니다.

이로하여, 가장 간단한 애니메이션 프레임에 맞춰 화살까지 쏘는 부분을 만들었습니다.