들어가며


게임 속에서 플레이어가 드론을 사용하게 되면 드론의 카메라로 시야가 전환되면서 드론을 조종하게 됩니다. 저는 언리얼에서 그런 드론을 구현하고 싶었고 그래서 Drone Tutorial을 참고하여 드론을 구현해보았습니다.

이 글에서는 그 과정을 글로 써보며 새롭게 알게된 것들을 다시 한번 정리해보려고 합니다.



0. 드론 설정



드론은 기본적으로 pawn 블루 프린트 클래스로 생성했습니다. 그 후 Box collider와 SkeletalMesh를 추가해준 뒤 collider에서 BlockAllDynamic을 적용하여 지형지물과 충돌할 수 있도록 하였습니다. BlockAllDynamic은 여러 충돌 채널에 대한 미리 정의된 설정인 충돌 프리셋 중 하나로 Collision ref에 의하면 기본적으로 모든 액터를 막는 설정입니다.

또 FloatingPawnMovement를 추가하였는데 이는 CharacterMovementComponent와는 달리 중력이 없이 간단한 물리 기반 이동을 구현하려고할 떄 사용한다고 합니다. 네트워크 동기화의 제한이 있다고하는데 실제 멀티플레이 시 고려해보아야할 수도 있겠습니다.

마지막으로 SceneCaptureComponent를 추가하였습니다. 이 컴포넌트는 이번에 처음 보았는데 씬을 캡처하여 특정 Render Target에 렌더링하는데 사용된다고 합니다. 주로 미니맵, 거울, 보안 카메라 구현에 사용된다고하는데 저는 드론의 시야를 보여주기 위해 사용했습니다. 생성 후 Scene Capture항목에서 다음과 같이 Render Target을 설정해주고 Capture Source를 Final Color로 바꿔주었습니다. 이렇게하면 모든 렌더링과 후처리 효과가 적용된 최종 색상을 캡처하게 됩니다.


1. RenderTarget과 Widget 설정

RenderTarget은 생성 후 다음과 같이 X, Y 사이즈를 세팅해주었습니다. 이후 RenderTarget에서 Create Material을 진행하여 Material을 만들어주었습니다.



이렇게 만들어진 Material은 아래와 같고 User Interface로 설정해주고 Final color를 사용하도록 설정해주었습니다. 이 Material은 렌더링될 DroneScreen_widget에 있는 image의 brush에 넣어질 것입니다. 이 brush에 RenderTarget을 바로 넣을 수도 있지만 여러 동적 효과를 제공하기 위해 Material로 만들어준 후 넣어주게되었습니다. 이 때 브러시란 그 UI 요소에 적용할 그래픽 리소스를 정의하는 구조체입니다.



이렇게 DroneScreen_widget을 설정한 후 이 widget을 전체 화면에 넣어주기 위한 widget을 만들어주어 최종 화면을 완성합니다.



2. 플레이어와 드론 관계 맺기

우선 BP_FirstPersonCharacter(이하 FPC)에 BP_Drone 변수를 추가한 뒤 맵의 드론을 할당해놓았습니다. 이를 통해 BP_FPC의 Event Graph에서 Drone을 사용할 수 있도록 하였습니다.



3. 드론으로 넘어가기

InputAction으로 2번 키를 지정하여 2번 키를 누르면 플레이어의 움직임을 멈추고, Drone의 Activate 함수를 작동시키도록 했습니다.

Drone의 Activate 함수는 일련의 과정을 거쳐 작동합니다. 우선 Drone의 State를 검사하고 Idle이라면 플레이어의 Controller를 가져오는 과정을 실행합니다.



Controller를 가져오는 과정은 다음과 같습니다. 우선 Player Pawn을 가져온 뒤, 거기서 Player Controller를 가져옵니다. 게임이 시작될 때 Controller는 제어할 Pawn을 소유하게되는데 Pawn은 자신을 제어하는 Controller에 대한 참조를 포함하고 있기때문입니다.



이후 1번에서 생성해 둔 widget을 viewport에 추가하는 과정을 거칩니다.



이후 드론으로 제어권을 넘기는 Possess 과정을 거치게 됩니다. 소유권을 드론이 가져온 이후 Set View Target With Blend를 부르게 되는데 이는 부드럽게 플레이어의 시점을 변경하는데 사용됩니다.



4. 드론의 움직임

드론의 움직임을 구현하는 것은 간단하게 작성할 수 있습니다. 축의 움직임을 받아오고, Actor의 forward vector와 곱하여 그 값을 이용하여 Add Input Vector를 실행하면되기때문입니다.



주의해야할 것은 마우스에 따른 드론의 회전을 구현하기 위해 다음과 같이 구현해놓은 뒤, Use Controller Rotation Yaw 옵션을 체크해주어야한다는 것입니다. 이 옵션이 true로 설정되어야 Pawn이 플레이어의 컨트롤러를 이용하여 회전가능합니다.



5. 플레이어로 복귀

플레이어로 복귀하는 것은 드론에 Deactivate함수를 만들어서 구현하였습니다. 우선 아래와 같이 플레이어에게 다시 소유권을 넘깁니다.


그 후 변수들을 다시 초기화시키고 Widget을 부모에게서 제거해줍니다.


6. 흑백효과 적용



좀 더 현실적인 군용 드론 카메라와 같은 효과를 주기 위해 저는 드론 카메라 영상에 흑백 효과를 줘보기로했습니다. 그렇게 하기위해서는 두 가지 기능을 사용했습니다.

첫번째로 만들어준 Material에 흑백으로 만들어주는 후처리를 추가하였습니다. rgb에 특정 벡터를 내적한 결과를 이용하면 자연스럽게 이미지를 흑백화시킬 수 있습니다.



그 후 SceneCaptureComponent에 tint효과에서 회색을 추가하여 좀 더 어두운 색을 만들어주었습니다.



7. 고도와 거리 표시

드론 카메라 영상에 좀 더 사실감을 더해주기 위하여 고도와 거리를 표시해주기로 하였습니다. 사실 두 개 모두 구현 방식은 똑같으니 고도 기준으로 적겠습니다.

가장 핵심이 되는 노드는 Line Trace By Channel이었는데요, Actor Location을 이용하여 Line Trace를 할 지점을 선정해주고 그것을 이용하여 얻어낸 거리를 변수에 저장해주었습니다.

이 떄 처음에는 Trace Channel이 Visibility로 되어있었는데 이를 Camera로 수정해주었습니다.


8. 사소한 사항

마지막으로 SceneCaptureComponent에서 Custom Near Clipping Plane옵션을 주었습니다. 이 옵션은 카메라가 렌더링할 제일 근접한 평면을 의미하는 것으로 0으로 설정하게되면 드론이 바닥에 닿았을 때 화면이 이상하게 렌더링되는 일을 막기 위해 사용하였습니다.