Notice
Recent Posts
Recent Comments
Link
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

MOONSUN

[UE5] Animation Montage(몽타주) : 콤보 공격 구현 본문

UE5

[UE5] Animation Montage(몽타주) : 콤보 공격 구현

MoonSun_v 2026. 4. 7. 10:55

 

이전 글에서 StateMachine으로 애니메이션을 전환 했었는데,

 

만약 4개의 공격 애니메이션이 있고,

연속으로 공격 명령을 내리면 콤보 공격처럼 각 공격 애니메이션을 순서대로 연계해야 한다면?

Attack1 → Attack2 → Attack3 → Attack4 ...

 

이전처럼 StateMachine 방식으로 관리한다면

→ 상태/전이 관리가 매우 복잡해져서, 스테이트 머신 설계가 복잡해지는 단점이 있다.

 

스테이트 머신의 확장 없이 특정 상황에서 원하는 애니메이션을 발동 시키는 애니메이션 몽타주 라는 기능이 있다!

 

 

Animation Montage 란?

StateMachine을 건드리지 않고 특정 애니메이션을 실행한다.
  • 원하는 타이밍에 재생 가능
  • 순차 연결(콤보) 구현 가능
  • 이벤트(Notify) 기반 제어 가능

 


 

애니메이션 3개 가지고 콤보 공격 만들어보자.

Attack1 → Attack2 → Attack3 (콤보)
  • 공격 타이밍 맞으면 → 다음 공격 이어짐
  • 타이밍 놓치면 → 콤보 끊기고 처음으로 돌아감

 

1. 콤보 시스템 전체 구조

입력 → 캐릭터 코드 → AnimInstance → Montage → Section 이동
  • 입력은 Character에서 처리
  • 애니메이션 제어는 Montage가 담당
  • 실제 흐름 제어는 Section 이동으로 처리

 

 

 

2. 몽타주 구성 (Sections)

 

Attack1 → Attack2 → Attack3

 

  1. 애니메이션 3개를 Montage에 배치 (지그재그로 들어감)

 

2. 각 애니메이션을 Section으로 분리

  • 각 애니메이션들은 Section으로 분리해서 처리할 수 있다.
  • 오른쪽에는 기본적으로 Section별로 자동 연결된 걸 볼 수 있음

  • Section끼리 연결 끊기.

 

왜? → 콤보는 “조건부로 다음 섹션으로 이동”해야 하기 때문

(연결되어있으면 자동으로 넘어가니까..)

 

 

Character 에 몽타주 추가

 

 

 

 

 

4. 몽타주 재생 (Character 코드)

이제 공격 입력이 들어오면 Montage를 재생하도록 구현한다.

 

먼저, Attack을 위한 IA와 IMC를 추가한 뒤, 입력 바인딩을 설정한다.

IA

 

IMC

 

입력 바인딩

EIC->BindAction(IA_Attack, ETriggerEvent::Triggered,this, &ATPSPlayer::PlayAttackMontage);

 

Montage 재생 함수

void ATPSPlayer::PlayAttackMontage()
{
	UAnimInstance*AnimInstance = GetMesh()->GetAnimInstance();
	
		if (AnimInstance&&AttackMontage)
		    {
					AnimInstance->Montage_Play(AttackMontage);
		    }
}

(중요) Montage는 AnimInstance를 통해 재생해야 한다

 

 

 

 

5. AnimGraph 설정 (Slot 추가)

Montage는 Slot을 통해서만 출력에 반영된다
StateMachine → Slot → Output Pose

 

(우리는 모든 상황에서 몽타주를 재생할 거라서 Output Pose와 StateMachine 사이에 몽타주 재생 노드 추가)

 

  • StateMachine가 기본 포즈 생성
  • Montage는 중간에 끼어들어 애니메이션을 덮어쓴다.

즉, Slot이 없으면 Montage는 재생되어도 화면에 안 보임

 

 

 

 

8. 입력 처리 로직 (Character → AnimInstance)

void ATPSPlayer::PlayAttackMontage()
{
		UAnimInstance*AnimInstance =GetMesh()->GetAnimInstance();
		
		if (!AnimInstance||!AttackMontage)return;
		
		// 몽타주가 이미 실행 중인지 확인
		if (AnimInstance->Montage_IsPlaying(AttackMontage))
		    {
		// 이미 공격 중이면 → 콤보 입력만 저장
		UABAnimInstance*ABAnim =Cast<UABAnimInstance>(AnimInstance);
			if (ABAnim)
		        {
						ABAnim->bComboInput =true;
		        }
		    }
		else
		    {
		// 첫 공격 시작
		AnimInstance->Montage_Play(AttackMontage);
		
		UABAnimInstance*ABAnim =Cast<UABAnimInstance>(AnimInstance);
		if (ABAnim)
		        {
		ABAnim->CurrentCombo =1;
		        }
	    }
}

흐름

공격 중 → 입력 → 예약 (bComboInput)
공격 아님 → 첫 공격 시작

 

 

 

9. Notify로 콤보 타이밍 제어

콤보는 Notify로 제어한다

 

Notify 역할 

Notify 역할
ComboWindowOpen 입력 가능 시작
ComboWindowClose 입력 가능 종료

 

Notify 위치

Open  : 60~70%
Close : 85~95%

 

(너무 뒤에 두면 입력 씹힘 이슈 발생.. )

 

 

아래처럼 Notify를 추가했다. 

 

 

(중요) Notify 종류

Montage Notify
  • C++ 함수로 안 들어올 수 있음

 

올바른 방식

Add Notify → New Notify...

 

이름

ComboWindowOpen
ComboWindowClose

 

규칙

AnimNotify_이름

 

함수 이름과 정확히 일치해야 호출됨

 

 

 

 

10. Notify 함수 구현 (AnimInstance)

void UABAnimInstance::AnimNotify_ComboWindowOpen()
{
    bCanNextCombo =true;
}
void UABAnimInstance::AnimNotify_ComboWindowClose()
{
    bCanNextCombo =false;

    // 입력이 들어왔으면 다음 콤보 진행
    if (bComboInput)
    {
        bComboInput =false;
        CurrentCombo++;

        FNameNextSection =FName(*FString::Printf(TEXT("Attack%d"),CurrentCombo));
        Montage_JumpToSection(NextSection);
    }
}

로직

1. 입력은 미리 저장됨
2. 타이밍이 열리면 (Open)
3. 닫힐 때 (Close)
   → 입력 있으면 다음 섹션 이동

 

 

 

11. OnMontageEnded (상태 초기화)

콤보 종료 시 상태 초기화

void UABAnimInstance::OnMontageEnded(UAnimMontage*Montage,boolbInterrupted)
{
		bCanNextCombo =false;
		bComboInput =false;
		CurrentCombo =0;
}

 

 

12. 전체 콤보 흐름

입력
 ↓
Montage 시작 (Attack1)
 ↓
Notify Open
 ↓
입력 저장
 ↓
Notify Close
 ↓
조건 만족 → 다음 Section (Attack2)
 ↓
반복
 ↓
끝나면 초기화

 

 

 

정리

공격 버튼을 누르면 몽타주를 재생하고, 공격 중에 다시 입력이 들어오면 그 입력을 저장해뒀다가,
Notify 타이밍에 다음 Section으로 넘겨서 콤보를 이어가라는 뜻

 

1. 몽타주를 만든다

  • Attack1, Attack2, Attack3 애니메이션을 하나의 Montage에 넣기
  • 각 구간을 Section으로 나누기
  • Section 자동 연결은 끊기

 

2. 공격 입력을 받으면 몽타주를 재생한다

  • 공격 중이 아니면 Montage_Play()로 시작
  • 첫 시작은 Attack1

 

3. 공격 중에 다시 입력이 들어오면 바로 재생하지 말고 “예약”만 한다

  • 예를 들어
  • bComboInput = true 이렇게 저장만 해둠

 

4. 각 공격 애니메이션 중간에 Notify를 넣는다

  • ComboWindowOpen : 지금부터 다음 공격 입력 받아도 됨
  • ComboWindowClose : 이제 입력 마감

 

5. ComboWindowClose 시점에 예약된 입력이 있으면 다음 Section으로 이동한다

  • Attack1 재생 중, 플레이어가 한 번 더 입력하면 
  • bComboInput = true
  • ComboWindowClose 도착 →  Attack2로 Montage_JumpToSection()

 

6. 입력이 없으면 콤보를 끝낸다

  • Attack1만 하고 종료
  • 몽타주 끝나면 상태 초기화

 

 

https://youtu.be/zK-CmHPIAgc