[62. Switching Blendspaces]

 

무기를 들었을 때의 새로운 애니메이션이 필요한 때이다.

 

애셋들을 다운로드하고 무기를 든 상태의 Idle/Walk/Run 블렌드 스페이스를 만들어 준다.

기존에 Idle/Walk/Run에 만들어 뒀던 내용은 모두 삭제하고 새로운 스테이트 머신을 추가할 것이다.

 

 

 

평상시->무기 습득시 (nulltpr이 아니라면)

무기 장착 여부에 관계없이 Idle/Walk/Run은 동일하기 때문에 스테이트 머신 안의 스테이트 머신이 필요한 것이다.

 

Sprint도 똑같이 만들어주면 된다.

 

[63. Anim Montages (Attack!) #1]

 

애니메이션들을 합쳐서 선택적으로 재생할 수 있도록 해주는 유연한 툴이다.

 

결과적으로 이런 식으로 사용하는 것인데 슬롯에 대한 개념이 잡히지 않아서 글을 작성하기가 어렵다.

추후 슬롯에 대한 개념이 잡히면 다시 작성하도록 하고 해당 실습을 따라가기만 하는것으로 둔다.

 

[64. Anim Montages (Attack!) #2]

 

마우스 좌클릭시 공격 애니메이션이 실행되는 것 까지 잘 되었다.

하지만 공격모션 도중에도 이동이나 점프가 자유롭게 된다는 문제가 있다. 이것을 수정해야 한다.

 

이동을 막는것은 간단하다.

 

// Main.cpp
void AMain::MoveForward(float Value)
{
    if ((Controller != nullptr) && (Value != 0.0f) && (!bAttacking))
    // ...
}

/* Called for side to side input */
void AMain::MoveRight(float Value)
{
    if ((Controller != nullptr) && (Value != 0.0f) && (!bAttacking))
    // ...
}

 

공격중이라면 이동 자체가 일어나지 않도록 해주면 된다.

다만 이러면 또 문제가 발생한다. 현재까지의 구현 내용으로는 bAttacking이 false로 돌아오는 일이 없기때문에 한번 공격시 영원히 움직일 수 없게된다.

이 부분은 애니메이션 노티파이를 통해 공격 모션이 끝날 때 특정 함수를 호출하는 것으로 해결하도록 한다.

 

EndAttacking을 배치할 때 위치를 잘 봐야한다. 섹션 이후가 아닌 섹션 이전에 와야 의도한 대로 작동할 것이다.

 

// Main.h
public:
    UFUNCTION(BlueprintCallable)
    void AttackEnd();
    
// Main.cpp
void AMain::AttackEnd()
{
    bAttacking = false;
}

 

노티파이가 호출할 함수이다. bAttacking을 false로 만들어주면 다시 이동이 가능해질 것이다.

 

노티파이를 설정했다면 이벤트그래프에서 표시가 될 것이다.

 

AnimNotify_ 라는 접두어가 붙은 이벤트가 새로 생성된다. 애니메이션 재생 도중에 노티파이가 설정된 구간을 지나면 이벤트를 호출하는 개념이다.

 

이제 공격 도중 움직일 수 없고 공격 모션이 끝나면 다시 이동할 수 있게 잘 수정되었다.

하지만 문제가 한가지 또 있다. 좌클릭을 연속으로 입력하거나 입력을 유지하고 있으면 공격 모션이 계속 초기화 되어 재생되는 것이다.

 

 

// Main.cpp
void AMain::Attack()
{
    // 1회성에 한해 공격하도록 함
    if (!bAttacking)
    {
        bAttacking = true;

        UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
        if (AnimInstance && CombatMontage)
        {
            // 몽타주 재생. 1.35배만큼 빠르게 재생
            AnimInstance->Montage_Play(CombatMontage, 1.35f);
            // 섹션으로 건너 뜀
            AnimInstance->Montage_JumpToSection(FName("Attack_1"), CombatMontage);
        }
    }
}

void AMain::AttackEnd()
{
    bAttacking = false;

    // 공격이 끝났음에도 마우스를 계속 누르고 있다면 다시 공격 실행
    if (bLMBDown)
    {
        Attack();
    }
}

 

이것 또한 간단하게 수정이 가능하다. Attack의 구현부를 bAttacking으로 모두 감싸면 한번 실행될 때 true가 되므로 이후로는 실행이 되지 않는다. 추가로 마우스를 계속 누르고 있을 때 공격모션이 계속 이루어지는것이 편리하므로 해당 부분도 겸사겸사 간단하게 처리한다.

 

[65. Anim Montages (Attack!) #3]

 

공격 모션을 추가하고 공격시 매번 같은 모션이 나오는것이 아닌, 무작위로 재생하게끔 하면 게임이 단조롭지 않을 것이다.

 

void AMain::Attack()
{
    if (!bAttacking)
    {
        bAttacking = true;

        UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
        if (AnimInstance && CombatMontage)
        {
            // 0-1 사이의 난수 발생
            int32 Section = FMath::RandRange(0, 1);
            switch (Section)
            {
            case 0:
                AnimInstance->Montage_Play(CombatMontage, 2.2f);
                AnimInstance->Montage_JumpToSection(FName("Attack_1"), CombatMontage);
                break;
            case 1:
                AnimInstance->Montage_Play(CombatMontage, 1.8f);
                AnimInstance->Montage_JumpToSection(FName("Attack_2"), CombatMontage);
                break;
            default:
                ;
            }
        }
    }
}

 

몽타주 섹션에서 이어진 프리뷰까지 끊어주면 공격 모션이 랜덤하게 재생된다.

 

[정리]

 

  • 애니메이션 몽타주는 여러개의 애니메이션을 엮어서 만들 수 있다. 섹션으로 나누어서 특정 섹션만 반복하거나 섹션끼리 연달아서 재생할 수도 있다.
  • 애니메이션 몽타주의 슬롯에 대한 명확한 설명을 찾기가 어렵다. 사용 예를 정확히 체감하지 못해서 그런 것 같다.
    관련 링크: https://docs.unrealengine.com/5.0/ko/animation-slots-in-unreal-engine/
  •  애니메이션 몽타주에서 노티파이를 이용해서 특정 모션에 이벤트를 발생시킬 수 있다.

 

'언리얼 엔진 > UE4 C++' 카테고리의 다른 글

[UE C++] Combat #4  (0) 2022.09.11
[UE C++] Combat #3  (0) 2022.09.11
[UE C++] Combat #1  (0) 2022.09.10
[UE C++] Gameplay Mechanics #7  (0) 2022.09.09
[UE C++] Gameplay Mechanics #6  (0) 2022.09.09

+ Recent posts