![언리얼5-19 C++ <장애물 피하기(5) - 마무리[2]>](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd6zvE7%2FbtsKRi1VUf2%2FuK9fe82KNE0EKn4T5nPqtk%2Fimg.png)
지난 글인 언리얼5-18 C++ <장애물 피하기(4) - 마무리[1]>에서 5번, 위 아래로 움직이는 발판밟고 이동하는 부분까지 제작해보았다.
이번 글에서는 6번, 회전하고 있는 기다란 발판을 밟고 이동할 수 있도록 제작해보자
콘텐츠 브라우저에서 [C++ Classes > AdventureTrap] 폴더에서 Obstacle C++ Class에 우클릭하고 이 클래스를 기반으로 하는 블루프린트를 하나 생성한다
이름은 BP_Obstacle5로 한 후에 생성해보자
발판의 역할을 할 메시를 [Content > EnvironmentPack1 > Meshes > EnvironmentPack_1] 폴더에서 찾아보자
(다른 메시를 변형해서 사용해도 되지만 간단하게 SM_Bridge_01 메시를 사용하였다)
SM_Bridge_01 메시를 끌어다 놓고 컴파일과 저장을 한 뒤에,
배치를 하고 나서 메시의 회전값을 주고 시뮬레이션을 해보면
피벗(Pivot)을 중심으로 회전하게 된다.
여기서 기즈모(Gizmo), 피벗(Pivot)의 개념에 대해 아주 간단하게 알아보자면
Gizmo는 오브젝트를 조작(이동, 회전, 스케일)하기 위한 도구로, 시각적으로 표현된다.
Pivot은 객체의 변환 중심점을 정의하는 '기준 위치'이다 (추상적인 개념이기 때문에 눈에 보이지는 않는다)
이 Pivot은 위치, 회전, 크기 조정의 중심점이 되고 객체 자체의 내부 위치에 존재하며, 레벨 에디터나 블루프린트에서 객체를 변환할 때 Pivot을 기준으로 적용된다
Pivot이 위치, 회전, 크기 조정의 중심점이 된다고 했는데, 그렇다면 Gizmo만 이동하면 Pivot 또한 따라오게 될까?
이를 알아보기 위해 레벨 데이터에서 Gizmo를 옮겨보자 ('Alt' + 마우스 휠 클릭을 한 상태에서 드래그를 하면 이동 수 있다)
[기즈모를 이동시키는 것은 큰 오브젝트나 복잡한 씬에서 세밀한 작업이 가능하거나, 작업의 기준점을 통일 시키는 등 장점이 많다]
그리고 Gizmo를 기준으로 메시를 회전시키면, 메시가 중앙으로 이동된 기즈모를 중심으로 회전하는 것을 볼 수 있는데
그렇다면 "Gizmo가 Pivot의 위치를 변화시키는 것 아닌가?" 라고 생각할 수 있다.
이때 시각적으로는 마치 Gizmo에 의해 Pivot이 이동된 것 처럼 보일 수 있지만 실제로 메시의 Pivot은 모서리 끝부분에서 변경되지 않았고, 단지 Gizmo가 이동된 위치에서 회전 작업이 수행된 것일 뿐이다
그래서 다른 곳을 클릭했다가 다시 메시를 선택하면 Gizmo는 원래 위치(모서리 끝)으로 돌아오는 것을 확인할 수 있다[이는 Gizmo의 이동이 일시적 조작 도구의 위치 변경일 뿐, Pivot 자체의 위치를 바꾸지 않는다는 것을 의미한다]
Pivot의 위치를 일시적이 아닌 영구적으로 바꾸기 위해서는 Set as Pivot Offset과 같은 작업을 통해 위치를 저장하는 과정이 필요한데,
Gizmo의 위치를 옮긴 상태에서 메시에 우클릭을 한 후, [Pivot > Set as Pivot Offset]을 선택해서 PIvot의 위치를 저장하면 된다
이후 다른 작업을 하고 다시 돌아와도 이 메시를 이동, 회전, 크기를 조절하는 기준(Pivot)의 위치가 고정된다
하지만 [Alt + 'S'] 단축키를 사용해서 시뮬레이션을 해보면, Pivot 의 위치가 옮겨지면서 다시 모서리를 기준으로 회전을 하게 된다
이는 처음에 블루프린트 에디터에서 설정한 값이 유지되고 있기 때문인데,
플레이 버튼을 누르면 블루프린트는 초기화 된 상태를 기준으로 오브젝트를 다시 배치하거나 정렬한다. 즉, 레벨 에디터에서 [Alt + 휠 클릭 -> Set as Pivot Offset] 과정으로 Pivot의 위치를 이동했다고 하더라도, 이 정보는 레벨 에디터 환경에서 저장되는 것이고 '플레이' 시에는 블루프린트에서 정의된 기본 상태로 복원이 된다.
그러면 "Pivot의 위치를 블루프린트에서 변경하면 되는 것 아닌가?" 라고 생각할 수 있는데, 틀린 말은 아니다.
하지만 블루프린트에서 Pivot의 위치를 변경하려면 Scene Root가 중심에 올 수 있도록 수동으로 하나씩 조절해야 한다는 단점이 존재한다. 이 방법은 시간이 많이 걸릴 뿐만 아니라 Scene Root가 중앙에 위치하도록 하는 것이 정확하지가 않다
여기서 Scene Root란, 블루프린트 내에서 '모든 컴포넌트의 최상위 부모로 작동하는' 기본 루트 노드이다.
Scene Root는 블루프린트 내의 월드 좌표계와 개별 컴포넌트 간의 로컬 좌표계를 연결하는 '기준점'(고정 위치)이 되고, 모든 자식 컴포넌트의 위치, 회전, 스케일을 관리하게 된다
[여기서 자식 컴포넌트는 SM_Bridge_01 메시이기 때문에 Scene Root는 이 Static Mesh의 위치, 회전, 스케일을 담당한다]
그래서 우리는 모델링 툴(Modeling Tool)이라는 것을 이용해서 Pivot의 위치를 영구적으로 옮길 것이다
상단의 메뉴 바에서 Selection Mode를 'Modeling' 으로 변경한다. [단축키: 'Shift' + '5']
그러면 이렇게 메시의 형태를 변경할 수 있는 모델링 툴이 나오는데, 왼쪽의 XForm 카테고리를 선택하면 오른쪽에 'Edit Pivot'으로 적혀있는 버튼이 있다.
그리고 Pivot의 위치를 옮기고자 하는 메시를 클릭한 후 'Edit Pivot' 버튼을 누르게 되면 이렇게 Pivot의 위치를 옮길 수 있게 되는데,
여기서도 위치를 수동으로 조절할 수도 있지만 우리는 메시의 중심을 기준으로 회전시킬 예정이기 때문에
왼쪽의 'Box Positions' 부분에서 Top을 선택해서 Pivot의 위치가 메시의 중심에 오게 한다
변경사항을 저장하기 위해서 아래의 Accept를 누르면 Pivot의 위치가 영구적으로 저장되게 된다
여기서 주의할 점은, 경고 문구에 적혀있는 것처럼 이 설정은 선택한 메시에만 적용되는 것이 아니라,
모든 SM_Bridge_01 스태틱 메시에 직접적으로 적용되기 때문에 앞으로 사용되는 SM_Bridge_01 메시는 Pivot의 위치가 Top으로 변경되어 있을 것이다.
이를 막기 위해서는 복사본을 미리 만들어 두어야 한다
Static Mesh 자산에 직접적으로 변경하였기 때문에, 블루프린트 에디터를 확인해 보면 SM_Bridge_01 스태틱 메시의 중앙에 Pivot Point가 위치해 있는 것을 확인 할 수 있다.
이 변경된 블루프린트를 사용하기 위해서 기존에 존재했던 메시를 지우고 다시 Content 폴더에 있는 BP_Obstacle5 블루프린트를 배치하게 되면
회전값을 주었을 때 정상적으로 중심을 기준으로 회전하는 것을 확인할 수 있다
이 다음은 7번, 나왔다 들어갔다 하는 발판을 제작해보자
이 장애물도 마찬가지로 C++ Classes 폴더의 Obstacle Class에 우클릭을 해서, 블루프린트를 생성한다
[블루프린트 이름은 BP_Obstacle6로 만들어보자]
Content Drawer에서 [All > Content > EnvironmentPack1 > Meshes > EnvironmentPack1] 폴더를 찾아 발판 역할을 할 메시를 찾아준다. [본인은 SM_StoneFloor_SeperatedStones 메시를 선택하였다]
이 발판은 여러개를 배치하기 때문에, 레벨 에디터에서 일일이 이동 값을 하나씩 적용하기 보다는 블루프린트에서 미리 값을 저장하는 것이 좋을 것이다
왼쪽 컴포넌트 창에서 BP_Obstacle6를 선택하고 Details 패널에서 ObjectMoveDistance 변수를 350 정도로 바꾸어 준다
그리고 변경사항을 적용하기 위해 컴파일과 저장을 해준다
이제 배치를 해 줄 차례인데, 원통 모양의 성을 돌면서 밟고 올라갈 수 있도록 해야한다.
그러기 위해서는 발판의 시작위치를 다르게 하는데, ObjectVelocity 변수는 각 발판마다 X축이나 Y축에 음수값이나 양수값을 입력하여 이동하는 방식을 변경하면 된다 [본인은 변수의 절댓값을 300정도로 주었다]
이런 식으로 발판에 따라 ObjectVelocity 값을 변경해서 모든 발판을 배치하면,
시뮬레이션을 했을 때 각 발판의 설정 값에 따라 움직이는 것을 확인할 수 있다
다음으로는 8번, 회전하는 발판을 밟고 이동하는 작업을 진행해보자
이 또한 지난번에 사용했던 발판을 재사용할 것이다
위아래로 움직이는 발판을 제작할 때 사용했던 애셋을 가져와서 [Alt키를 누른채로 끌면 쉽게 복사&붙여넣기가 가능하다]
다리를 만들어주면 되는데, 이때 회전만 적용시킬 것이기 때문에 Detail패널에서 Object Velocity값을 0으로 만들어준다
그리고 위치를 조금씩 조정해서 위치를 맞춰준다
다리를 건너는 것을 방해하는 장애물을 만들기 위해서 C++클래스를 기반으로 블루프린트를 생성해준다
[이름은 BP_RotationDoor 이라고 지었다]
콘텐츠 브라우저에서 EnvironmentPack_1 폴더를 찾고, SM_DungeonBaseDoorFrame 메시를 끌어서 넣어준다
이 장애물은 발판을 기준으로 회전시킬 것이기 때문에 도구 툴을 이용해서 크기를 조정해준 다음, 컴파일과 저장을 해준다
이제 Y축 회전부분에 값을 주고 시뮬레이션을 하면 발판을 기준으로 회전하는 장애물 하나가 완성이 된다
그 다음에는 중간에 쉴 수 있는 쉼터를 하나 배치해준다
마지막 과정으로 9번, 양옆으로 빠르게 움직이는 장애물을 피해서 도착지점까지 이동하는 과정을 진행할 것이다
먼저 콘텐츠 브라우저의 EnvironmentPack_1 폴더에서 SM_KnightCastle_Hallway_Floor 메시를 찾아 다리를 만들어준다
그리고 장애물 역할을 할 클래스를 만들기 위해서 C++클래스를 기반으로 한 블루프린트를 하나 생성해준다
이제 장애물 역할을 할 메시를 선택해주면 된다 [본인은 SM_Rock04 메시를 선택하였다]
이렇게 만든 메시를 좌우로 이동할 수 있도록 배치해주고, 위치에 따라서 ObjectVelocity값을 적절하게 넣어준다
[오른쪽 X:-200, Y:-400, MoveDistance: 1300 / 왼쪽 X:200, Y:400, MoveDistance: 1300]
여기에서도 아까 다루어본 것처럼 피벗의 위치나 방향을 회전해서 X축이나 Y축값만 주고도 동작시킬 수 있다.
작업이 끝나고 컴파일과 저장 후 시뮬레이션을 돌려보면
이렇게 장애물들이 다리를 기준으로 좌우로 움직이는 것을 확인할 수 있다
마지막으로 도착지점까지 만들어주면 프로젝트의 완성이다.
이번 프로젝트에서는 언리얼엔진과 C++를 활용하여 이동과 회전을 제어하는 코드를 작성해서 장애물 피하기 맵을 제작해보았다. 이 과정에서 블루프린트를 통해 빠르게 프로토타입을 구현하고 게임의 전반적인 흐름을 설계한 뒤, 세부적인 이동과 회전 기능을 대입해보았다.
프로젝트를 진행하며 얻은 배움을 바탕으로, 앞으로는 더 복잡한 시스템과 기능을 추가해 볼 계획이다.
VR게임 개발을 위한 언리얼엔진/C++ 공부한 내용 끄적이기...
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!