[62. Switching Blendspaces]
무기를 들었을 때의 새로운 애니메이션이 필요한 때이다.
애셋들을 다운로드하고 무기를 든 상태의 Idle/Walk/Run 블렌드 스페이스를 만들어 준다.
기존에 Idle/Walk/Run에 만들어 뒀던 내용은 모두 삭제하고 새로운 스테이트 머신을 추가할 것이다.
무기 장착 여부에 관계없이 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 |