UE4

[UE4] 물리엔진

Honey Badger 2022. 10. 20. 02:52

콜리전(Collision)

물리 엔진을 활용하려면 콜리전이라 불리는 물리적 충돌영역을 알아야 한다. 언리얼 엔진에서 콜리전은 크게 세가지 방법으로 제작할 수 있다.

1. 스태틱메시 에셋

  스태틱메시 에셋에 콜리전 영역을 심는 방법이다. 스태틱메시를 더블 클릭하면 열리는 스태틱메시 에디터에서 해당 콜리전 영역을 설정하고 확인할 수 있다. 스태틱메시에 콜리전을 심으면 비주얼과 충돌이라는 두가지 기능을 설정할 수 있어 관리가 간편해진다.

 

2. 기본 도형 컴포넌트

  구체, 박스, 캡슐의 기본 도형을 사용해 충돌 영역을 지정하는 방법이다. 스태틱메시와 별도로 충돌 영역을 제작하는데 사용한다. 스켈레탈 메시를 움직일 때 주로 사용한다.

 

3. 피직스 에셋

일반적으로 캐릭터의 이동은 캡슐 컴포넌트를 사용해 처리한다. 하지만 특정 상황에서 캐릭터의 각 관절이 흐느적거리는 헝겊 인형 효과를 구현할 때 이 피직스 에셋을 사용한다. 캐릭터의 각 부위에 기본 도형으로 충돌 영역을 설정하고 이를 연결해 캐릭터의 물리를 설정한다. 피직스 에셋은 스켈레탈 메시에만 사용할 수 있다.

 

 

물리설정

물리 설정은 크게 다음 세가지로 구분된다.

 

1. 콜리전 체널과 기본 반응

2. 콜리전 체널의 용도

3. 다른 콜리전 체널과의 반응

 

충돌체에 반드시 하나의 콜리전 채널을 설정해야 한다. 언리얼 엔진은 8개의 기본 콜리전 채널을 제공하고 액터의 종류에 따라 위의 콜리전 채널 중 하나를 충돌체를 사용하는 컴포넌트에 부여하고 있다. 

 

콜리전 체널은 각각 용도에 따라 두가지로 나뉜다.

1. 오브젝트 채널 : 콜리전 영역에 지정하는 콜리전 채널.

2. 트레이스 채널 : 어떤 행동에 설정하는 콜리전 채널.

 

각 콜리전 채널의 용도는 다음과 같다.

1. WorldStatic : 움직이지 않는 정적인 배경액터에 사용하는 콜리전 채널. 주로 스태틱메시 엑터에 있는 스태틱메시 컴포넌트에 사용한다.

2. WorldDynamic : 움직이는 액터에 사용하는 콜리전 채널이다. 블루프린트에 속한 스태틱메시 컴포넌트에 사용한다. 

3. Pawn : 플레이어가 조종하는 물체에 주로 사용한다. 캐릭터의 충돌을 담당하는 캡슐 컴포넌트에 설정된다. 

4. Visibility  : 배경 물체가 시각적으로 보이는지 탐지하는 데 사용한다. 탐지에서 폰은 제외된다. 마우스로 물체를 선택하는 피킹 기능을 구현할 때 사용한다.

5. Camera : 카메라 설정을 위해 카메라와 목표물 간에 장애물이 있는지 탐지하는 데 사용한다. 

6. PhysicsBody : 물리 시뮬레이션으로 움직이는 컴포넌트에 설정한다. 

 

ex) 캐릭터의 루트 컴포넌트인 캡슐 컴포넌트에는 Pawn이라는 콜리전 채널이 설정되어있다. 

 

Collision Enabled

  해당 컴포넌트에서 물리 기능을 어떻게 사용할지 지정한다.

1. Query : 두 물체의 충돌 영역이 서로 겹치는지(Overlap) 테스트하는 설정이다. 충돌 영역이 오버랩되면 관련 컴포넌트에 BeginOverlap 이벤트가 발생한다. 지정한 영역에 물체가 충돌하는지 탐지하는 레이캐스트나 스윕 기능도 Query에 속한다.

2. Physics : 물리적인 시뮬레이션을 사용할 때 설정한다.

3. Query ans Physics : 위의 두 기능을 모두 사용하는 설정이다. 이 설정을 사용하면 모든 기능이 잘 동작하지만, 물리 엔진이 수행할 계산량이 많아지므로, 액터마다 자신에게 필요한 기능을 파악해 Query나 Physics 설정만 지정하는 것이 효과적이다. 

 

콜리전 반응

해당 컴포넌트에 설정된 콜리전 채널이 상대방과 어떻게 반응할지 지정한다. 

1. 무시 : 콜리전이 있어도 아무 충돌이 일어나지 않는다. 

2. 겹침(Overlap) : 무시와 동일하게 물체가 뚫고 지나갈 수 있지만 이벤트를 발생시킨다. 

3. 블록 : 물체가 뚫고 지나가지 못하도록 막는다. 

 

  언리얼 물리엔진은 무시 반응을 최대화하고, 블록 반응을 최소화하도록 동작한다. 예를 들어 충돌 컴포넌트 중 하나를 무시 반응으로 설정하면 겹침과 블록 반응은 발생하지 않는다. 겹침 반응으로 설정하면 앞으로 블록 반응은 발생하지 않는다. 이렇게 두 컴포넌트 간에 물리적 반응이 일어날 때 각 컴포넌트에는 특별한 이벤트가 발생한다. 겹침반응에는 BeginOverlap이벤트가 발생하고 블록 반응에는 Hit 이벤트가 발생한다. 블록반응에서의 BeginOverlap이벤트는 Generates Overlap Events항목이 양쪽 모두 체크돼 있어야만 발생한다. 

 

오브젝트 채널 직접 만들기

오브젝트 채널을 직접 추가했다면 가장 먼저 해야 할 일은 이미 만들어진 다른 콜리전 프리셋과 문제없도록 설정하는 작업이다. 콜리전 채널의 기본 반응을 블록으로 설정했다면 블록 기능에 관련된 콜리전 프리셋과는 문제가 없지만, 블록 반응을 하면 안되는 다른 콜리전 프리셋들이 있다 보니 이에 맞게 조율해야한다. 신경 써야 할 프리셋들은 다음과 같다.

 

- OverlapAll : 겹침

- Trigger : 겹침

- OverlapAllDynamic : 겹침

- IgnoreOnlyPawn : 폰만 충돌을 무시하도록 설정한다. 무시

- OverlapOnlyPawn : 폰에만 겹침 이벤트가 발동하도록 설정한다. 겹침

- Spactator : 외부 관중과의 충돌을 설정한다. 무시

- CharacterMesh : 캐릭터 메시에 사용하는 물리 설정이다. 무시

- RagDoll : 스켈레탈 메시의 피직스 에셋 물리를 가동하기 위한 물리 설정. 무시

- UI : UI 요소에 사용하는 설정이다. 겹침

 

위의 모든 콜리전 프리셋과의 반응 설정을 완료했다면, 우리가 만든 프리셋을 해당 컴포넌트가 사용하도록 코드로 기본값을 지정하자.

GetCapsuleComponent()->SetCollisionProfileName(TEXT("MyCharacter"));

 

트레이스채널 직접 만들기

  물리엔진을 사용해 캐릭터의 공격 기능을 구현해본다. 공격이라는 행동은 애니메이션이 일어나는 특정 타이밍에 공격 범위 안에 위치한 액터가 있는지 감지하고 감지된 액터에게 대미지를 전달하는 행위라고 할 수 있다. 언리얼 엔진은 행동에 대한 판정을 위해 트레이스 채널이라는 카테고리로 콜리전 채널을 제공한다. 트레이스 채널의 기본 반응을 무시로 설정해 추가한 후 하단의 Preset 설정으로 이동해 앞서 제작한 콜리전 프리셋 MyCharacter을 들어가보면 트레이스 채널에 Attack이 생긴 것을 볼 수 있다. Attack 트레이스 채널의 기본 반응은 무시이므로, MyCharacter콜리전 프리셋과의 설정을 블록으로 지정하게 되면 앞으로 Attack 트레이스 채널을 사용하는 액터의 물리적 행동은 MyCharacter 콜리전 프리셋에만 반응하게 된다.  

 

 

물리 엔진을 활용한 공격 로직 구현하기

  물리는 월드의 기능이므로 GetWorld()함수를 사용해 월드에게 명령을 내려야 한다. 트레이스 채널을 사용해 물리적 충돌 여부를 가리는 함수 중 하나로 SweepSingleByChannel이 있다. 이 함수는 기본 도형을 인자로 받은 후 시작 지점에서 끝 지점까지 쓸면서(Sweep) 해당 영역 내에 물리 판정이 일어났는지를 조사한다. 이 함수에서 사용할 파라미터 설정은 꽤나 복잡하다. 

 

- HitResult : 물리적 충돌이 탐지된 경우 관련된 정보를 담을 구조체.

- Start : 탐색을 시작할 위치.

- End : 탐색을 끝낼 위치.

- Rot : 탐색에 사용할 도형의 회전.

- TraceChannel : 물리 충돌 감지에 사용할 트레이스 체널 정보.

- CollisionShape : 탐색에 사용할 기본 도형 정보. 구체, 캡슐, 박스를 사용한다. 

- Params : 탐색 방법에 대한 설정 값을 모아둔 구조체.

- ResponseRarams : 탐색 반응을 설정하기 위한 구조체.

 

  공격의 범위를 설정하기 위해 반지름이 50cm인 구를 만들고, 이를 캐릭터 위치에서 정면 방향으로 2미터 떨어진 곳까지 쓸어서 충돌하는 물체가 있는지 감지해본다. 이때 TraceChannel은 Attack Channel을 사용한다. 이 값은 언리얼 엔진에서 정의한 ECollisionChannel 열거형으로 가져올 수 있는데 C++코드에서 이를 가져오는 방법이 다소 복잡하다. 

 

언리얼 엔진은 게임에서 활용할 수 있도록 총 32개의 콜리전 채널을 제공한다. 32개중 여덟 개는 위에서 설명했듯이 언리얼 엔진이 기본으로 사용하고, 여섯 개는 엔진에서 다른 용도로 사용하도록 예약돼 있다. 우리가 만드는 게임 프로젝트에서는 이를 뺀 나머지 18개만 사용할 수 있다. 게임 프로젝트에서 새로 생성하는 오브젝트, 트레이스 채널은 ECC_GameTraceChannel 1~18번까지 중에서 하나를 배정받는다. 어떤 값을 배정받았는지는 프로젝트의 Config 폴더에 있는 DefaultEngine.ini에서 확인할 수 있다. 

 

  FCollisionShape::MakeSphere 함수를 사용하면 공격 탐지에 사용할 도형을 제작할 수 있다. 도형의 기본값을 지정하고, 탐색 영역은 시작위치는 액터가 있는 곳으로 , 끝날 위치는 액터 시선 방향으로 200cm 떨어진 곳으로 정한다. 탐색 영역을 지정했다면 다음으로 탐색 방법을 설정한다. 공격 명령을 내리는 자신은 이 탐색에 감지되지 않도록 포인터 this를 무시할 액터 목록에 넣어줘야 한다. 그리고 마지막 인자인 탐색 반응 설정은 구조체의 기본값을 사용한다.

 

  마지막으로 액터의 충돌이 탐지된 경우 충돌된 액터에 관련된 정보를 얻기 위해 구조체를 넘겨준다. FHitResult 구조체로 지역변수를 하나 생성하고, 이를 첫번째 인자에 넣어주면 탐색 기능이 완성된다.