본문으로 바로가기

[Unreal Engine 5] 공격 판정

category UnrealEngine/기능 2023. 9. 23. 20:14

충돌 채널의 설정

 

월드는 이 처럼 3가지의 충돌 판정을 제공하고있다.

충돌체와 충돌했는지를 판단하고, 해당 액터의 정보를 가져올 수 있다.

  • LineTrace : 지정한 방향으로 선을 그어, 어떤 물체가 투사했는지를 확인한다.
  • Sweep : LineTrace와 유사한데, 선이 아닌 특정 도형을 가지고 확인한다.
  • Overlap : 지정한 영역에 큰 범위의 도형을 설정해, 해당 영역과 물체가 교차했는지를 판단한다.

이러한 충돌 판정 기능을 구현하기 위해서는 언리얼 엔진이 제공하는 기본적인 물리 설정에

Trace Channel 과 Collision Profile을 생성해야 한다.

언리얼 엔진의 에디터에서 Edit - Project Settings를 눌러 프로젝트 세팅 화면을 열고, Collision 탭으로 진입한다.

이곳에서 Trace ChannelCollision Profile을 생성한다.

 

일단 Trace Channel부터 클릭해서 만들어보자

 

여기서 Default Response는, Trace 를 처리했을 때 '모든 오브젝트'들이 기본적으로 해당 Trace에 대해서 어떻게 반응할 것인지를 처리하는 것이다.

방법은 Block, Overlap, Ignore가 있다.

우리는 '모든 오브젝트' 가 아닌, 특정 Capsule Component를 들고있는 캐릭터만 해당 Trace에 반응을 할 것이므로 일단 'Ignore' 로 처리한다.

 

그리고 Preset을 클릭하고, New를 눌러 새로운 Profile을 만들어주자

우리의 ABActionTrace에 반응을 해야하므로, Block으로 설정한다.

그 전에 CollisionEnabledObjectType에 대해 설명한다.

CollisionEnabled : Collision을 처리하는 방법에 대해서 설명한다.

  • No Collision : 충돌 없음, Query와 Simulate를 다 사용하지 않아서 Collision을 사용하지 않는다는 것. 움직이는 오브젝트에서 최적의 퍼포먼스를 냅니다
  • Query Only : Query (Raycast, Sweep, overlap) 에만 충돌을 처리합니다. 
  • Physics Only : Simulate (RigidBody, Constraint) 에만 충돌을 처리합니다. 본 단위의 감지가 필요치는 않은 캐릭터의 2차 시뮬레이션에 좋습니다.
  • Collision Enabled : Query와 Simulate를 다 사용합니다.

ObjectType : 해당 프로필을 사용하는 Physics Body의 역할에 대해서 설정합니다.

  • WorldStatic : 이동하지 않는 액터에 대해서 사용합니다. 
  • WorldDynamic : 애니메이션 또는 Kinematic 같은 코드의 영향을 받아 움직이는 액터 유형에 사용됩니다. 예를 들어 열리는 문같은 것입니다.
  • Pawn : 플레이어 캐릭터같은 Pawn 유형에 대해서 사용합니다.
  • PhysicsBody : Physics Simulation으로 인해 움직이게 되는 캐릭터에 대해 사용합니다.
  • Vehicle : Vehicle 유형에 대해 사용됩니다.
  • Destructible : 우리가 파괴하는 어떤 물체에 대해서 사용합니다.

우리는 Pawn 형태에 대해서 사용할 것입니다.

최종적으로는 이런식으로 설정을 완료하였습니다.

 

또 하나의 Profile을 더 생성합니다.

어떠한 Pawn에 대해서 Trace 처리를 할 것이므로, 모든 오브젝트에 대해서 겹침 반응만 처리하는 Profile을 생성합니다.

 

우리가 Profile을 다 만들었다면,

저번에 만든 Animation Montage에서 '특정 프레임'에 공격 판정을 처리해야 한다.

그러기 위해서는 특정 프레임에 Animation Montage에서 Notify을 받아 처리를 해야하는데

이를 위해 기본적으로 제공하는 Notify를 사용해도 되지만, Custom Notify를 만들어 처리하겠다.

 

Add C++ Class를 통해 AnimNotify를 검색하면, AnimNotify 이름은 AnimNotify_* 로 만들어지는것을 볼 수 있다.

이 것처럼 우리의 프로젝트에서 해당 네이밍 규칙에 맞춰 클래스를 만드는 것이 좋다.

 

컴파일이 끝나고, 우리가 공격 처리를 했던 Montage로 돌아가

공격 처리를 할때의 프레임에 Notify를 우클릭 해서 검색해보자 

다음과 같이, 우리가 만든 AnimNotify_* 가 생성되어 있는 것을 볼 수 있다.

 

이렇게 원하는 프레임에 추가하면된다.

 

이제 Notify가 호출될 때, 어떻게 처리할 것인지를 C++로 처리하면된다.

이를 위해서 AnimNotify_*에서 특정 callback의 함수를 재정의 해야 한다.

 

해당 함수를 override 해야하므로, 복사해서 자식에서 새로 재정의한다.

 

우리가 어떠한 Notify를 커스텀 했을 때, 특정 Actor에 대해서 Notify를 처리하려면 의존성을 갖게 된다.

의존성을 갖게 되면, 새로운 Notify가, 그리고 새로운 Actor가 생길때마다 해당 class를 또 정의해주어야 한다는 것인데

이는 매우 많은 작업을 일으킬 수 있다.

그러므로 UAnimNotify_AttackHitCheck는 Interface를 사용해 공용으로 처리할 수 있게 만들것이다.

 

Add C++ Class 를 클릭하여 맨 밑으로 내려보면 Unreal Interface가 있다.

이를 만들어준다.

 

우리가 어떠한 Notify가 일어나면, 

해당 Notify를 일으킨 오브젝트의 Interface를 가져와 AttackHitCheck를 호출해 주고

각각의 AttackHitCheck를 할 오브젝트들은 각자의 방식대로 AttackHitCheck를 하면된다.

 

이제 실제로 Notify에서는 넘어온 오브젝트가

해당 Interface를 구현했는지 확인하고, 했다면 호출해주면 된다.

 

이제 World Trace 함수를 사용해서 AttackHitCheck를 정의해야하는데, 해당 함수는 다음과 같이 정해진다.

 

1. 처리 방법 : Linetrace, Sweep, Overlap 중 하나를 선택

2. 대상 : 

  • Test : 무엇인가 감지되었는지를 테스트
  • Single, AnyTest : 감지된 '단일' 물체 정보를 반환
  • Multi : 감지된 '모든 물체' 정보를 반환

3. 처리 설정 :

  • ByChannel : Trace Channel 정보를 사용해 감지
  • ByObjectType : 물체에 지정된 물리 타입 정보를 사용해 감지
  • ByProfile : 프로필 정보를 사용해 감지

우리는

캐릭터의 위치 시선방향에서 물체가 있는지 감지

작은 구체를 만들어, 시선 방향으로 특정 거리까지만 체크

하나의 물체

Trace Channel을 사용

처리방법 : Sweep ( 작은 구체를 만들어 시선 방향으로 특정 거리까지만 )

대상 : Single (하나의 물체)

처리 설정 : Trace Channel 을 사용

이므로

사용할 함수는 SweepSingleByChannel이 된다.

 

이제 AttackHitCheck 함수를 정의한다.

 

대부분의 내용은 알 것이라 생각하고, 특정 함수와 인자에 대해서만 설명한다.

 

FCollsionQueryParams : 해당 충돌에 대해서 설정을 해주는 파라미터들을 정의한다.

해당 내용은 생성자를 보면 알 수 있다.

InTraceTag : 우리가 Collision을 분석할 때, Tag 정보(식별자 정보)로 사용되는 인자이다.

bInTraceComplex : 복잡한 형태의 충돌체( Capsule이나 Sphere 같은 convex 형태의 단순한 볼륨을 대상으로 충돌을 감지하면 빠르게 처리가 가능하고 물리 시뮬레이션도 구현할 수 있는데, 복잡한 Mesh를 처리하면 올라 섰는지? 정도만 처리가 가능하다. ) 를 감지할 것인지에 대해 체크

InIgnoreActor : 충돌 체크를 무시할 오브젝트들

 

SweepSingleByChannel에서 특이한점은 ECollisionChannel::ECC_GameTraceChannel1 인데

이는 우리가 기존에 만들었던 ABAction이 포함된 채널이다.

이는 DefaultEngine.ini을 열면 확인할 수 있다.

 

이제 SweepSingleByChannel을 통해 반환된 bool값을 체크해 충돌이 되었는지를 확인할 수 있다.

만약 충돌 범위를 체크하고 싶다면 밑의 코드와 같이 작성하면 된다.