삼인칭 템플릿의 마지막인 Combat을 리뷰해보겠다.
근접 전투(Melee combat)가 구현된 템플릿인데, 플레이 해보면 철권 같은 느낌이다.
주된 기능으로
콤보 어택과 차지어택,
인터페이스를 통한 데미지(이펙트 및 카메라 효과),
체력 위젯,
AI Enemy 등이 있다.
우선 기본적인 움직임을 만들고 스프링암위 위치를 조정한다.
이 때 캐릭터의 이동은 시선 방향으로(Looking Direction)으로 하여 캐릭터 시선을 고정한다.

5.6버전 애니메이션의 블렌드스페이스를 보면 Strafe 값을 축으로 가지며
Strafe는 캐릭터의 좌우 이동을 판정한다.

캐릭터의 Right Vector와 속도 벡터의 내적(Dot product)로 설정되어 있다.

먼저 캐릭터에 체력바를 표시하기 위해
사용자 위젯 블루프린트 클래스를 생성하고,
오버레이, 보더, 프로그래스바를 추가한다.

프로그래스바의 퍼센트와 색상을 조정할 커스텀 이벤트를 만들어준다.

캐릭터 클래스로 돌아가서, 컴포넌트에서 위젯 컴포넌트를 추가한 뒤
유저 인터페이스 카테고리에서 스페이스를 Screen으로 하고, 위젯 클래스를 설정한 뒤 크기를 설정한다.

이후 블루프린트의 BeginPlay 이벤트에서 변수 설정과 색상까지 전달한다.
Life Bar 컴포넌트가 있지만 내부 이벤트에 접근하기 위해 캐스팅한 후 변수를 설정했다.


다음으로 콤보어택을 위해 애님 몽타주를 먼저 보면

애님 몽타주에서 세 개의 시퀀스를 추가한 후 각 애니메이션에서
Hit가 발생할 경우에는 Do Melee Attack Damage 애님 노티파이 클래스를,
이후에 Check Combo 애님 노티파이를 호출한다.
각각의 클래스는 물체에 충돌했을 때와 몽타주 섹션을 점프하는 역할을 한다.
애님 노티파이와 블루프린트 클래스 사이는 인터페이스로 연결되어 있어 애님 노티파이에서 Check Combo 메시지를 전달한다.

이제 캐릭터의 이벤트 그래프로 가서
입력 액션이 발생할 때마다
Is Attacking이 True일 경우 공격이 입력된 시간을 계속해서 갱신해주고,

Is Attacking이 False일 경우에는 아래 그래프를 보면
공격 입력이 처음 들어오고, 애님 몽타주를 재생할 때
애니메이션 몽타주가 섹션으로 되어있어 한 섹션만 재생하게 된다.
On Completed와 On Interrupted 조건에서 이벤트를 호출하게 되어
저장된 공격 입력 시간이 임계치 이하일 경우(공격 입력이 정해진 시간 내 들어옴) 다시 애니메이션을 재생하고
공격 입력이 없거나 임계치보다 클 경우 그대로 끝이 난다.
이 커스텀 이벤트가 없어도 되지만, 특정 상태에서 콤보가 재생이 안되는 부분을 보완하기 위한 것으로 보인다.

재생될 애니메이션의 몽타주 섹션을 점프 하는 역할은 Check Combo가 하게 된다.
먼저 저장된 공격 입력 시간을 확인해주고,

콤보 카운트를 증가킨 후 몽타주 섹션의 인덱스로 사용해서 몽타주 색션을 점프시킨다.
그러므로, Check Combo 이벤트는 새로운 입력이 몇 번 들어오건 마지막 입력이 Check Combo를 호출한 시간 내에 들어오면 몽타주를 점프시켜 다음 섹션을 재생시킨다.


다음 단계로 차지 어택 애님 몽타주를 만들고,
애니메이션에 진입하여 차징하는 동안은 Charged 섹션에 루프를 걸어 애니메이션을 반복시킨다.

캐릭터 블루프린트로 가서,
차지 공격 입력에 대해 IsAttacking이 true일 경우 Cached Attack Input Time을 여기서도 설정해준다.
이렇게 하면 공격중에 차지 공격을 눌러도 콤보 어택을 수핼할 수 있다.

다음 Is Attacking이 false인 경우
Has Looped Charged Attack 변수를 false로 초기화 하고, 애님 몽타주를 재생해준다.
몽타주가 끝난 뒤 호출되는 함수는 Combo Attack에서와 같은 로직이다.

이제 차지 입력이 해제 되었을 때 애님 몽타주를 점프해주면 된다.
Check Charged Attack 이벤트는 애님 노티파이에서 호출이 되는 이벤트다.
애님 몽타주를 보면 진입 시와 반복 전에 호출하는데, 호출 될 때 Has Looped Charged Attack을 true로 설정한다.
Montage Jump to Section을 호출하는 두 가지 경우가 있는데,
반복구간에 진입하기 전에 키를 해제할 경우 Has Looped Charged Attack이 true가 되지 않았기 때문에
Check Charged Attack 이벤트에서 몽타주 점프를 실행하고,
반복 구간에 진입한 이후 키를 해제하면 Has Looped Charged Attack이 true가 되어 키 해제 이벤트에서 몽타주 점프가 실행된다.
차지 공격이 바로 실행되지 않도록 진입 구간과 루프 구간을 나누어 설계한 것으로 보인다.


이제 충돌 이벤트를 만들면,
애님 몽타주에서 충돌 판정을 위해 노티파이를 만들고 인터페이스를 통해 메시지를 전달했다.
캐릭터에서 메시지를 받아 충돌을 판정하는 그래프를 만들면 된다.
애님 노티파이 클래스에서 Socket Bone Name으로 펀치할 손이나 발의 소켓 이름을 전달한다.
그리고 이 소켓 이름의 위치에서부터 sphere 형태의 레이 트레이싱을 수행한다.
이 떄 오브젝트 타입으로 다른 Pawn이나 World Dynamics로 설정한다.

이후 결과에 대해 Hit가 발생한 오브젝트들에게 Apply Damage를 호출한다.
이때, 메시지에는 데미지, 공격한 액터, 데미지 위치와 impulse를 함꼐 전달한다.

마지막으로 Camera Shake 효과를 적용한다.
Default Camera Shake Base 클래스를 상속받아 만든 클래스이다.
Default Camera Shake Base는 카메라 흔들림 효과(Camera Shake Effect) 를 생성하기 위한 기본 클래스(Base Class)이다.
이는 게임 내에서 폭발, 충격, 달리기 등 강한 움직임이나 피드백을 줄 때 시각적인 효과로 사용된다.

이제 오브젝트를 만들고 물리 시뮬레이션을 킨 뒤
이벤트 그래프에 Apply Damage 이벤트로 Impulse와 VFX 효과를 추가해준다.


박스 오브젝트도 존재하는데 전체적으로 비슷한 그래프를 가진다.
대신 박스는 커스텀 이벤트로 Destroy 되었을 때 시각적 효과가 더 존재한다.

커스텀 이벤트인 Destroy Box가 호출되었을 때
먼저 오브젝트 타입을 Visibile로 하여 물체가 보이기만 하게 한 뒤, 색상을 약간 변경한다.
타임라인으로 Actor의 Scale을 변경시킨 뒤 액터를 Destroy시킨다.
Set Actor Scale 3D함수를 사용할 때 주의할 점으로, Static Mesh가 루트 컴포넌트여야 한다.


마지막으로 콜리전 프리셋을 다루어 보겠다.
콜리전 프리셋을 맞게 설정하지 않아 충돌처리가 잘 되지 않았던 적이 많았다.

언리얼 엔진에는 액터마다 고유의 오브젝트 타입(Object Type) 을 가지며,
각 오브젝트 타입별로 다른 채널에 대해 충돌 반응을 설정할 수 있다.
충돌 반응은 다음의 세 가지 유형 중 하나로 설정된다.
Ignore(무시): 해당 채널에 대해서 충돌을 전혀 감지하지 않는다. 트레이스나 충돌 이벤트가 발생하지 않음
Overlap(오버랩): 충돌은 발생하지 않지만 두 액터가 겹쳤다는 사실을 감지하여 OnOverlap 이벤트 등을 발생시킨다.
Block(블록): 충돌이 발생하며, 두 액터의 이동이 물리적으로 막힌다. 충돌 반응은 OnHit 이벤트 등으로 처리할 수 있다.
보통은 BlockAll, BlockAllDynamic, OverlapAll, OverlapAllDynamic 등 엔진에서 제공하는 콜리전 프리셋을 사용하지만,
요구사항에 따라 커스텀 채널과 오브젝트 타입을 직접 정의하여 정교한 충돌 처리 로직을 구현할 수도 있다.
이러한 충돌 설정은 컴포넌트의 Details 패널에서 변경할 수 있으며, Blueprint 또는 C++에서도 동적으로 설정할 수 있다.
리뷰는 여기까지 하면 마무리 되었다.
이 템플릿도 적 AI가 더 있지만 나중에 전반적인 AI 기능들을 한번에 다루어보면 좋을 것 같다.