이번 영상에서는 유니티에서 에셋을 전달하기 위해서 사용되는 유니티 패키지에 대해서 알아보도록 하겠습니다.
압축파일 전달
유니티에 익숙하지 못한 입문자일 때는 프로젝트나 프로젝트 안에 있는 텍스처, 머티리얼, 프리팹, 스크립트 같은 에셋을 공유하거나 전달하려고 프로젝트 전체를 압축해서 보내거나 전달할 에셋을 선택하여 압축해서 보내는 방법을 주로 사용했었습니다.
저도 유니티를 처음 배웠을 때는 그렇게 많이 했었죠.
하지만 이 방법을 사용하면 굉장히 많은 문제가 발생합니다.
전체 프로젝트를 압축해서 옮기면 프로젝트의 크기에 따라서 압축 파일의 용량이 너무 커져서 옮기기가 어려워 집니다.
물론 프로젝트에 필요한 폴더만 묶어서 압축하면 훨씬 압축파일의 용량이 줄어들지만, 이렇게 옮기면 프로젝트를 받은 사람이 처음 열 때 시간이 많이 걸린다는 단점도 있습니다.
그리고 압축 파일 이름에 버전을 적어둬도 어떤 게 어떤 버전인지 헷갈리는 문제도 발생합니다.
거기에 가장 치명적인 단점으로는 수동으로 파일을 선택할 때는 프리팹이나 씬에 포함된 오브젝트의 참조 관계, 즉 어떤 프로퍼티에 어떤 프리팹이나 텍스처 등의 에셋들이 꽂혀있는지 전부 알 수 없기 때문에 빠지는 파일이 생길 수 있습니다.
그렇게 되면 전달된 에셋들이 제대로 동작하지 않는 문제가 발생하게 됩니다.
유니티 패키지
앞에서 말한 압축 파일로 에셋을 전달하는 방법에서 발생하는 문제를 해결할 수 있는게 바로 유니티 패키지입니다.
먼저 유니티 패키지를 만드는 방법부터 보여드리겠습니다.
유니티 에디터의 프로젝트 뷰에서 유니티 패키지로 익스포트할 에셋을 선택합니다.
그 에셋에 우클릭하고 [Export Package]를 선택합니다.
그러면 Exporting Package 창이 뜨면서 선택한 에셋과 연관된 에셋, 즉 종속성을 가진 에셋들이 함께 자동으로 선택됩니다.
물론 프로젝트 크기가 커지면 이 종속성이 상당히 복잡해서 정말 필요한 에셋 뿐만 아니라 곁다리 수준으로만 엮인 에셋들도 선택되서 쓸데없는 에셋들이 함께 익스포트되는 경우도 있기 때문에 잘 확인하고 꼭 익스포트할 에셋들만 선택해야 합니다.
그리고 창에서 Include dependency 체크를 해제하면 정말 선택한 에셋만 잡히는데 지금 선택한 프리팹의 경우에는 필요한 3D 모델, 애니메이터 컨트롤러 등이 모두 빠지기 때문에 빈 오브젝트만 익스포트됩니다.
그래서 이 Include dependency 옵션은 보통은 정말 필요한 리소스 에셋이나 스크립트 에셋만 빼내야 할 때 체크를 해제해주면 됩니다.
이렇게 익스포트할 에셋을 모두 선택한 다음에는 Export 버튼을 누르고 저장하고자 하는 위치에 이 패키지가 무엇을 담고 있는지 확실하게 알 수 있는 이름으로 저장해주면 됩니다.
그리고나서 이 유니티 패키지를 임포트할 프로젝트를 실행하고 패키지 파일을 더블클릭해주면 패키지 안에 담긴 에셋들을 그 프로젝트에 넣을 수 있게 됩니다.
버전 관리 도구로써는? 글쎄...
이렇게 유니티 패키지를 사용하면 자신이 개발한 내용이나 기능, 에셋 등을 다른 사람에게 공유할 수 있게 됩니다.
하지만 유니티 패키지를 프로젝트의 버전 관리 도구처럼 사용하려고 해서는 안됩니다.
프로젝트의 버전 관리는 개발 내용의 최신화가 아주 중요한데, 패키지를 전달 받은 다른 개발자가 자신의 프로젝트에 적용하는 작업을 까먹고 안할 수도 있고, 전달 과정에서 몇몇 사람들을 빼먹고 전달하는 경우도 있을 수 있어서 프로젝트의 최신화를 공통적으로 유지하기 어렵습니다.
그리고 이 패키지를 임포트하는 작업은 같은 에셋이 존재하는 경우에 수정 사항을 완전히 덮어씌워버리기 때문에 작업 내용이 겹치거나 잘못된 작업이 임포트되었을 때, 되돌릴 방법이 없다는 것도 문제입니다.
그렇기 때문에 유니티 패키지는 프로젝트의 버전 관리를 위한 방법으로는 적절하지 못하며, 프로젝트 버전 관리는 SVN이나 깃을 사용하는 것이 좋습니다.
깃허브를 이용해서 유니티 프로젝트를 관리하는 방법을 소개하는 영상은 영상 링크를 통해서 확인하실 수 있습니다.
유니티 패키지 사용법
그러면 유니티 패키지는 어디에 사용하면 좋은지 궁금하신 분들이 계실 겁니다.
물론 저는 거기에 답변을 드려야겠죠.
유니티 패키지는 필요한 에셋들을 선택해서 각 에셋 사이의 참조나 종속성 연결을 끊기지 않게 가져올 수 있다는 점에 초점을 맞춰야 합니다.
그래서 필요한 에셋들을 다른 프로젝트에서 가져올 수 있는 것입니다.
예를 들어 예전에 만들었던 게임이 있다고 해봅시다.
그리고 그 다음 게임을 만들려고 하는데 예전에 만들었던 게임과 유사한 형태의 인벤토리 시스템을 넣으려고 한다고 가정해봅시다.
이러면 새 프로젝트에서 완전히 새롭게 인벤토리 시스템을 짜는 것보다 이전 프로젝트에 들어있는 인벤토리 에셋들을 유니티 패키지로 익스포트해서 가져오는 편이 훨씬 나을 겁니다.
또 다른 예시로는 새 프로젝트를 만들어두고 여기에는 인벤토리 시스템만을 구현하는 방식으로 아예 특수한 기능만 구현하는 유니티 프로젝트를 만드는 것입니다.
그리고 이 프로젝트에는 이 시스템을 어떻게 사용해야 하는지 알려주는 샘플 씬과 각종 에셋, 그리고 설명서까지 넣어둡니다.
그 다음에 이 인벤토리 시스템이 필요한 프로젝트가 생기면 이 인벤토리만 구현된 프로젝트에서 관련 에셋들을 유니티 패키지로 익스포트해서 인벤토리 시스템이 필요한 프로젝트에 임포트 시키는 거죠.
사실 대부분의 유니티 에셋 스토어에 올라온 에셋들이 이렇게 필요한 기능만 구현된 프로젝트에서 패키지만 익스포트하는 방식과 유사하게 동작합니다.
아웃트로
이번 영상에서는 유니티에서 에셋을 묶어서 전달하는 기능인 유니티 패키지에 대해서 알아보았습니다.
이상 베르의 게임 개발 유튜브였습니다. 감사합니다.
[유니티 어필리에이트 프로그램]
아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.
유니티에서 게임 오브젝트는 씬에 배치될 수 있는 오브젝트를 의미한다. 이 게임 오브젝트에 어떤 컴포넌트가 붙는가에 따라서 그 게임 오브젝트의 역할이 결정되는데, 씬에 하나만 배치되는 오브젝트는 컴포넌트를 직접 부착해서 배치할 수는 있지만 똑같은 오브젝트를 많이 배치해야 되는 경우에 매번 배치할 때마다 필요한 컴포넌트를 부착하는 작업을 해야한다면 이것은 매우 비효율적인 작업이 된다.
일일이 게임 오브젝트를 생성한 다음 컴포넌트를 붙이는 비효율에서 벗어나기 위해서 제일 처음 만들어진 게임 오브젝트를 복사해서 배치할 수도 있는데, 이것은 또 다른 비효율적인 작업에 봉착하게 된다. 만약 이렇게 붙여넣은 오브젝트들의 크기를 전부 2배로 키워야 한다면? 그럼 붙여넣은 게임 오브젝트들을 일일이 찾아서 스케일 값을 바꿔주어야 한다. 이것 역시 심각하게 비효율적인 작업이다.
이러한 예시 이외에 어떤 게임 오브젝트를 게임이 진행하는 도중에 생성해서 배치해야 된다면, 코드 상에서 빈 게임 오브젝트를 생성하고, 거기에 필요한 컴포넌트를 붙여서 일일이 초기화해서 배치를 하는 것 역시 비효율적이다.
비효율적인 작업들 1 : 새 오브젝트마다 손수 컴포넌트 붙이고 설정하기
앞서 제시한 예시들을 하나씩 따라가보자.
우리는 이제 씬에 이른바 "Elegance Black Box"라고 명명된 검은색의 Black Box 컴포넌트가 부착된 상자를 여러 개 배치하려고 한다. 이 멋진 검은 상자를 만들기 위해서 우리는 다음과 같은 작업을 해야한다.
먼저 새 상자를 만든다.
새 상자의 이름을 "Elegance Black Box"로 변경한다.
그 다음 머티리얼에 검은 색 머티리얼을 넣고 Black Box 컴포넌트를 붙여준다(사실 따로 순서를 진행할 수도 있지만 그만큼 번거롭고 지루해지기 때문에 그냥 합쳤다).
자 총 4단계의 과정을 거쳤다. 이 작업을 만들고자 하는 "Elegance Black Box"의 갯수만큼 반복하면 된다. 고작 4단계인데 이렇게 번거롭다. 만약 더 복잡한 구조의 게임 오브젝트라면 어떻겠는가?
비효율적인 작업들 2 : 배치된 게임 오브젝트 복제하기
유니티 엔진에서는 복제하고자 하는 게임 오브젝트를 선택하고 우클릭하여 [Duplicate] 항목을 선택하거나 [Ctrl + D] 단축키를 눌러서 복제할 수 있다.
와! 일일이 새 게임 오브젝트를 만들고 컴포넌트를 붙이는 작업을 하지 않아도 된다! 혁명적인가? 분명 여기까지는 혁명적이다. 하지만 원수같은 기획자들이 "Elegance Black Box"를 좀 더 우아하게 강조하기 위해서 크기를 25% 키우자고 주장했다.
그나마 예시에서는 갯수가 적고 하이어라키 뷰에서 오브젝트가 흩어져 있지 않아서 모두 선택해서 빠르게 해결했다. 하지만 하이어라키 뷰에서 다른 게임 오브젝트 밑에 숨어있다거나 흩어져있다면 일일이 찾아서 수정해야 한다. 물론 하이어라키 뷰의 검색 기능을 이용하면 훌륭하게 해결할 수 있을 지도 모른다. 그러나 이런 검색 작업 역시 비효율적인것은 사실이다.
비효율적인 작업들 3 : 코드에서 동적으로 생성하기
이번에는 동료 디자이너가 "멋진 검은 상자가 게임 중에 동적으로 생성되면 좋겠는데!"라고 말했다.
public static BlackBox CreateNewBlackBox()
{
var newBox = GameObject.CreatePrimitive(PrimitiveType.Cube).AddComponent<BlackBox>();
거기에 당신은 위와 같이 블랙 박스를 생성하는 코드를 만들어 냈다. 이러면 끝난 것일까? 아니다. 디자이너가 블랙 박스에 대해서 수정사항을 가지고 올 때마다 당신은 코드를 수정해야 한다. 거기에 컴파일 시간은 덤이다! 그리고 지금은 간단한 오브젝트라 코드가 몇 줄 되지 않지만 복잡한 오브젝트면 코드의 양이 늘어나고 거기에 더불어 버그의 확률도 함께 상승한다.
우리의 구세주 프리팹
이러한 모든 문제를 해결하기 위해서 있는 것이 바로 프리팹이다. 프리팹은 게임 오브젝트와 거기에 붙여진 컴포넌트와 그 프로퍼티들을 에셋의 형태로 저장하는 것이다.
프리팹 만들기
프리팹을 만드는 방법은 아주 간단하다. 하이어라키 뷰에서 프리팹으로 만들고자 하는 게임 오브젝트를 선택해서 프로젝트 뷰로 끌어다 놓기만 하면 된다. 프리팹이 된 게임 오브젝트는 앞의 아이콘이 무채색 육면체에서 파란 육면체로 바뀐다.
배치된 게임 오브젝트 한꺼번에 변경하기
이번에도 아까 전처럼 씬에 배치된 모든 블랙 박스의 크기를 변경하고 싶을 수 있다. 프리팹으로는 이런 작업이 아주 간단하다.
프로젝트 뷰에서 원본 프리팹을 선택하고 프리팹의 크기를 변경해주면 씬에 배치된 모든 프리팹 인스턴스의 크기가 함께 변경된다. 하지만 이 방법은 씬에 배치된 각각의 인스턴스의 프로퍼티가 수정된 상태라면 적용되지 않으니 주의해야 한다.
프리팹 인스턴스에서 편집
위 예시에서는 프리팹 원본에서 수정된 것을 프리팹 인스턴스로 적용되는 내용이었다. 반대로 씬에 배치된 프리팹 인스턴스를 수정하고 이것을 원본 프리팹에 적용할 수도 있다. 씬에 배치된 프리팹 인스턴스 게임 오브젝트를 선택하면 일반 게임 오브젝트와는 다르게 인스펙터 뷰의 게임 오브젝트의 이름 아래에 Prefab : Open, Select, Override 버튼을 볼 수 있다.
여기서 Open 버튼을 선택하면 선택된 프리팹의 원본만을 수정할 수 있는 전용 씬으로 이동된다. 여기서는 프로젝트 뷰에서는 보이지 않는 프리팹 원본의 깊은 자식 오브젝트까지 열어서 수정할 수 있게 된다. 또한 수정된 프리팹의 내용은 자동으로 저장되며 하이어라키 뷰의 프리팹 아이콘 옆의 < 버튼을 클릭하면 다시 원래 씬으로 돌아올 수 있다.
원본 프리팹을 더블 클릭하거나 씬에 배치된 프리팹 인스턴스 옆의 > 버튼을 클릭해도 프리팹 수정 씬으로 들어올 수 있다.
Select 버튼을 클릭하면 프로젝트 뷰의 원본 프리팹이 바로 선택된다.
Override 버튼은 만약 프리팹 인스턴스에 원본 인스턴스와 달라진 점이 있다면 내용이 나타난다. 여기서 Revert All을 선택하면 프리팹 인스턴스의 변경 사항이 초기화되고 프리팹 원본 값으로 돌아간다. Apply All을 선택하면 프리팹 인스턴스의 수정 사항이 반대로 프리팹 원본에 덮어 씌워진다.
프리팹 인스턴스화
프로젝트 뷰에 존재하는 프리팹 원본은 에셋 상태로 이 상태 그대로는 게임 씬에서 보거나 사용할 수 없다. 이것을 게임 씬에 배치하고 사용할 수 있게 생성하는 과정을 인스턴스화라고 한다. 프리팹 인스턴스화는 게임 오브젝트의 Instantiate() 함수를 이용해서 할 수 있다.
프로젝트 뷰에 있는 게임 오브젝트는 크게 두 가지 방법으로 가져올 수 있다.
Resources 폴더에서 가져오기
첫 번째 방법은 Resources 폴더에서 가져오는 것이다. 이 방법은 어느 경로이든 무관하게 가져오고자 하는 프리팹이 프로젝트 뷰에서 Resources 폴더 안에 들어있기만 하면 된다. 단, Resources 폴더에 들어있는 파일들은 게임이 실행되면 무조건 메모리에 적재되기 때문에 메모리 이슈를 일으키고 싶지 않다면, 필요한 에셋만을 Resources 폴더에 넣어둘 것을 권장한다.
public static BlackBox CreateNewBlackBox()
{
var boxPrefab = Resources.Load<BlackBox>("Elegance Black Box");
return Instantiate(boxPrefab);
}
그 다음 Resources.Load() 함수로 Resources 폴더 안의 프리팹을 가져와서 Instantiate() 함수로 씬에 생성할 수 있다.
씬에 배치된 게임 오브젝트의 컴포넌트의 프로퍼티로 참조하기
public class BoxSpawn : MonoBehaviour
{
[SerializeField]
private GameObject boxPrefab;
private void Start()
{
Instantiate(boxPrefab);
}
}
두 번째 방법은 씬에 배치된 게임 오브젝트에 부착된 컴포넌트의 프로퍼티로 프리팹 원본을 참조하고 있다가 생성하는 방법이다.
씬에 Box Spawner 게임 오브젝트를 만들고 위에서 작성한 Box Spawn 컴포넌트를 부착하고 Box Prefab 프로퍼티에 프리팹을 할당해주면 된다. 그러면 게임이 시작되면 박스 스포너가 블랙 박스를 생성하는 것을 확인할 수 있다.
기타
위에서 제시한 방법 이외에도 에셋 번들에서 가져와서 생성하는 방법 등 다른 기능과 연계된 심화 방법들이 존재한다.
프리팹의 장점
게임 오브젝트가 프리팹화됨으로써 얻을 수 있는 장점은 굉장히 많다. 첫 번째는 재사용이 굉장히 편하다는 점이고, 씬에 흩어져서 배치된 프리팹의 인스턴스들을 한꺼번에 수정하기도 쉽다. 그리고 프로그래머가 컴포넌트만 제대로 만들어준다면, 게임 디자이너들이 프로그래머에게 요청하지 않고도 손쉽게 게임 요소들을 수정할 수 있다는 점이 제일 큰 장점이다.
[유니티 어필리에이트 프로그램]
아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.
에디터 레이아웃 구성의 한 가운데 있는 것은 Scene 뷰다. 유니티에서 씬(Scene)이라는 개념은 일종의 맵(Map)이나 레벨(Level)에 해당한다. 씬 뷰는 이러한 씬에 배경을 꾸미기위해 소품이나 배경 건물 등을 배치하는데 사용된다.
하이어라키(Hierarchy) 창
씬 뷰의 좌측에 있는 하이어라키 창은 씬에 배치되어 있는 오브젝트들을 보여준다. 가장 상단에 SampleScene이라는 이름으로 현재 열려있는 씬의 이름이 표시되고, 그 아래에 그 씬에 포함된 오브젝트들이 나타난다. 기본적으로 배치되어 있는 오브젝트는 Main Camera라는 이름의 카메라와, Directional Light라는 이름의 조명이다.
프로젝트(Project) 창
프로젝트 창은 현재 프로젝트에 포함된 텍스처나 모델링, 스크립트, 씬 등의 애셋(Asset)을 보여주는 창이다. 개발 경험이 많지 않은 경우에는 프로젝트 창에 애셋들이 추가되는 대로 중구난방으로 쌓아두는 일이 많은데, 애셋들을 적절하게 분류해서 정리해두는 버릇을 들여두는게 나중에 필요한 애셋을 찾거나 불필요한 애셋을 정리할 때 큰 도움이 되며, 개발 속도에도 긍정적인 영향을 미칠 것이다.
인스펙터(Inspector) 창
인스펙터 창은 지금은 아무 내용이 없지만, 하이어라키 창에서 씬에 배치된 오브젝트나 프로젝트 창에서 프로젝트에 포함된 애셋을 선택하면 그것에 대한 자세한 정보를 보여주는 역할을 한다.
하이어라키 창에서 메인 카메라 오브젝트를 선택하고 인스펙터 창을 보면 메인 카메라 오브젝트의 자세한 정보를 확인하고 수정할 수 있게 된다.
게임(Game) 창
씬 창 뒤에 탭으로 되어 있는 게임 창 탭을 선택하면 씬 창이 뒤로 전환되고 게임 창이 앞으로 나온다.
게임 창은 씬 창과 같이 씬을 보여주는 역할을 하지만, 게임 창은 씬 창과는 다르게 카메라가 보여주는 것만을 볼 수 있는 창이다. 즉, 실제 게임에서 보게 될 장면을 보여주는 창이다.
콘솔(Console) 창
콘솔 창은 개발도중에 발생한 에러나 경고, 개발자가 기능을 테스트하거나 값을 체크하기 위해 출력시킨 로그 등이 출력되는 창이다. 출력된 로그를 더블클릭하면 비주얼 스튜디오가 열리고 해당 로그가 출력된 스크립트의 위치로 이동하게 된다.
로그의 종류
유니티 엔진에서 로그는 크게 일반 로그, 경고 로그, 에러 로그로 나누어지고, 일반 로그는 데이터의 값이나 진행 상황, 상태를 체크하기 위해 사용되는 로그이고, 경고 로그는 치명적이지는 않지만 수정할 것을 권장하는 로그이며, 에러 로그는 게임이 정지하거나 기능에 심각한 이상이 발생하는 상황에 대한 로그이다.
세부적인 버튼의 내용은 다음과 같다.
뒤의 세 개 버튼은 각각 일반 로그, 경고 로그, 에러 로그 보기 버튼이며, 해당 버튼을 눌러서 원하는 종류의 로그만 볼 수 있다.
일반 로그만 활성화한 상태이다.
경고 로그만 활성화한 상태이다.
에러 로그만 활성화한 상태이다.
Clear 버튼은 현재까지 출력된 로그들을 모두 지운다.
Collapse 버튼은 같은 내용의 로그가 여러 번 출력되면 여러 줄로 표시하지 않고 한 줄로 표시하며 같은 내용의 로그가 몇 번이나 출력되었는지를 보여주는 기능이다. 이것은 로그의 순서가 중요하지 않고, 출력되었느냐 혹은 몇 회나 출력되었는지가 중요한 경우에 사용하게 된다.
Clear on Play 버튼은 에디터에서 플레이 버튼을 눌렀을 때, 남아있는 로그를 모두 지우고 플레이를 시작하게 만든다. 남아있는 이전에 띄운 로그가 남아있다면 플레이 중에 뜨는 로그가 보기 힘들어지는 경우가 많기 때문에 사용한다.
Error Pause 버튼은 플레이 도중에 에러 로그가 발생하면 플레이를 일시정지 시키는 버튼이다. 에러가 나도 플레이가 계속되면 에러가 발생하는 순간을 놓칠 수도 있기 때문에 에러가 발생한 순간을 잡아내기 위해서 사용하는 기능이다.
Editor 버튼은 에디터의 로그를 출력한다는 뜻의 버튼이다. 나중에 모바일 게임을 개발하다보면 APK로 빌드한 앱을 모바일 기기에 설치해서 컴퓨터와 연결하고 실행해서 실시간으로 로그를 보기위해서 사용되는 버튼이다.
애셋 스토어(Asset Store) 창
애셋 스토어 창은 다른 개발자들이 만든 게임 개발용 애셋들을 구매할 수 있는 창이다. 대규모 개발팀이나 회사는 게임에 필요한 모든 리소스들을 개발할 여력이 있겠지만, 소규모 개발팀이나 1인 개발자는 모든 리소스를 만들어내기 매우 어렵기 때문에 다른 사람이 만든 애셋을 구매해서 사용하면 더 빠르게 게임을 개발할 수 있다는 장점이 있다.
그 외의 창들
유니티 엔진에는 방금 화면 구성에서 소개한 창들 외에도 많은 종류의 창들이 존재한다.
에디터 상단의 메뉴 바에서 Window 메뉴를 클릭해서 드롭다운 메뉴를 펼치면 숨겨진 창들의 목록을 보고 필요한 창을 열어서 사용할 수 있다.
그 외의 버튼들
이 버튼들은 씬에 배치된 오브젝트를 이동, 회전, 크기 조절을 하는데 사용되는 버튼들이다.
이 버튼들은 에디터에서 게임을 실행, 일시정지, 한 프레임씩 넘기기를 하는 버튼이다.
좌측 버튼부터 순서대로, 팀단위 작업을 위한 유니티 콜라보(Collaborate) 버튼, 유니티가 제공하는 서비스 버튼, 계정 관리 버튼, 씬 창에서 보이기 원하는 레이어를 선택하는 버튼, 유니티 에디터의 레이아웃 버튼이다.
유니티 에디터 레이아웃 수정하기
유니티 에디터의 화면 구성은 사용자가 편한 방식으로 레이아웃을 수정할 수 있다.
위치를 수정하려고하는 창의 탭을 드래그해서 에디터에서 완전히 떼어내거나 다른 곳에 배치할 수 있다.
완전히 떼어낸 하이어라키 창
다른 위치에 배치한 하이어라키 창
각자 사용하기 편한 방식으로 레이아웃을 배치해보자.
수정한 레이아웃 저장하기
수정한 레이아웃은 저장해두고 언제든지 다시 불러올 수 있다. 에디터 우측 상단 구석에 Default 버튼을 클릭하면 드롭다운 메뉴 중에 Save Layout... 버튼을 클릭하면 수정한 레이아웃의 이름을 지어줄 수 있는 대화상자가 뜬다.
좌측부터 게임, 씬, 콘솔이 한 묶음으로 묶여있고, 그 다음엔 하이어라키와 프로젝트, 마지막으로 인스펙터로 나열되서 3-2-1로 배치되어 있으니 이 레이아웃의 이름을 Countdown이라고 저장하겠다.
레이아웃을 저장하고 나면 Default로 되어있던 버튼이 Countdown으로 되어있으며 추가한 Countdown 레이아웃이 드롭다운 목록에 추가되어 있는 것을 확인할 수 있다. 이렇게 레이아웃을 저장해두면, 레이아웃이 바뀌어도 언제든지 손쉽게 자주 사용하는 레이아웃으로 돌아올 수 있다.
[유니티 어필리에이트 프로그램]
아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.
이전 섹션에서는 C++ 내려보기 템플릿을 참고해서 일반적인 RPG처럼 마우스 클릭을 통해 캐릭터를 이동시키는 방법을 구현해보고 코드를 분석해본다.
프로젝트 세팅
RpgProject 라는 이름으로 새 프로젝트를 하나 만든다.
RpgProject를 생성한 뒤에는 내려보기 템플릿으로도 새 프로젝트를 하나 만드는데, 이것은 캐릭터의 메시와 애니메이션을 가져오기 위함이다.
제일 먼저 할 일은 내려보기 프로젝트에서 캐릭터의 메시와 애니메이션을 가져올 것이다. 방금 만든 내려보기 프로젝트의 콘텐츠 패널의 콘텐츠 폴더 하위에 Mannequin 폴더가 보일 것이다. 이 안에 캐릭터의 메시와 애니메이션이 들어있다. 이 폴더의 내용물들을 RpgProject로 옮겨야 한다. 이렇게 프로젝트에 포함된 애셋들을 다른 프로젝트로 옮기는 작업을 이주(Migrate)라고 한다. 직접 파일을 옮기지 않아도 언리얼 엔진에서는 이것을 도와주는 기능을 제공한다.
Mannequin 폴더에 우클릭을 하고, 이주... 를 선택한다. 애셋 리포트 창이 뜨면 리스트를 체크하고 확인 버튼을 누른다.
그 다음 대상 콘텐츠 폴더 선택 대화상자가 열리면 RpgProject 프로젝트의 Content 폴더를 찾아서 폴더 선택을 한다.
이주 작업이 끝난 뒤에 RpgProject로 가서 콘텐츠 브라우저 패널을 확인하면 내려보기 프로젝트에 있던 Mannequin 폴더와 그 안의 애셋들이 RpgProject에 성공적으로 옮겨진 것을 확인할 수 있다.
캐릭터의 메시와 애니메이션을 모두 이주시켰으면 그 다음은, 비주얼 스튜티오를 열고 솔루션 탐색기에서 RpgProject.Build.cs를 찾아서 소스파일을 연다.
Build.cs에서는 게임을 개발하면서 사용할 모듈을 추가하거나 뺄 수 있는데, 여기서는 두 가지 모듈을 추가할 것이다. 아래의 예시 코드와 같이 PublicDependencyModuleNames에 "NavigationSystem"과 "AIModule"을 추가해주자. NavigationSystem 모듈은 네비게이션 메시와 관련된 기능에 도움을 주는 모듈이고 AIModule 은 이름 그대로 AI 기능에 관련된 모듈이다. 클릭된 위치로 캐릭터를 이동시킬 때, 처리하는 코드를 일일이 만드는 대신, 이 두 모듈의 기능의 도움으로 내비게이션된 경로를 따라서 움직이도록 만들 예정이다.
if (Distance > 120.0f) { UAIBlueprintHelperLibrary::SimpleMoveToLocation(this, DestLocation); } } }
이 함수에서는 우선 컨트롤러가 소유하고 있는 폰을 가져와서 폰과 목적지 사이의 거리를 측정해서, 그 거리가 120 언리얼 유닛보다 크면 폰을 목적지로 이동시킨다. UAIBlueprintHelperLibrary클래스의 SimpleMoveToLocation() 함수는 프로그래머가 목적지로 폰을 이동시키기 위한 처리를 하는 모든 코드를 일일이 작성하는 대신에 간단한 함수 호출로 그 모든 일을 할 수 있도록 도와준다. 아까 전 프로젝트 세팅 단계에 모듈을 추가한 것은 이 기능을 사용하기 위해서 였다.
이 코드는 캐릭터의 무브먼트를 규정하는 코드로, 캐릭터를 이동시키기 전에 이동 방향과 현재 캐릭터의 방향이 다르면 캐릭터를 이동 방향으로 초당 640도의 회전 속도로 회전시킨다음 이동시킨다. 그리고 캐릭터의 이동을 평면으로 제한하고, 시작할 때 캐릭터의 위치가 평면을 벗어난 상태라면 가까운 평면으로 붙여서 시작되도록 한다. 여기서 평면이란 내비게이션 메시를 의미한다.