2017년 2월 14일 화요일

[언리얼4 RPG제작 2-2] 블루프린트 스크립팅

이번에는 액터 스스로 행동할 수 있게 만들어주는 블루프린트 스크립팅에 대해서 알아보겠다.

게임을 만든다는 것은 조작에 따라 서로 다른 이미지를 보여주는 소프트웨어를 만드는 일이다. 이 소프트웨어가 원하는대로 실행하기 위해 우리는 컴퓨터에게 명령을 내리게 될텐데, 기획 의도대로 소프트웨어가 동작하도록 컴퓨터 명령을 설계하는 작업을 프로그래밍(Programming)이라고 한다. 게임을 개발하던 초창기 시절에는 개발자들이 프로그래밍을 통해 컴퓨터에 전달할 명령을 세부적으로 지시하였다. 이 때는 프로젝트 크기도 작고 컴퓨터 사양도 그리 좋지 않았기 때문에, 사람보다는 기계가 읽기 편한 방식으로 명령을 설계했다. 하지만 게임 산업이 점점 발전하면서 게임 프로젝트의 규모가 커지면서, 프로그래밍쪽에 대해서는 게임 엔진에 맡기고 개발자들은 게임 콘텐츠에 대한 고민에 집중하는 형태로 개발 방식이 변해가고 있다. 게다가 프로그래밍에 대한 이해 없이도 컴퓨터에게 명령을 내릴 수 있도록, 프로그래밍 방식 또한 발전해왔다. 과거와 달리 필요한 부분에 인간이 사용하기 쉬운 형태로 컴퓨터 명령을 설계하는 작업을 구분해 스크립팅(Scripting)이라고 한다. 언리얼 엔진에서는 비주얼하게 선을 이어서 표현하는 방식의 블루프린트 스크립팅(Blueprint Scripting)이라는 기능을 제공한다.

[그림] 프로그래밍과 블루프린트 스크립팅의 비교

게임 엔진에서의 스크립팅은, 언제(When)에 해당하는 이벤트(Event)와 하다(Do)에 해당하는 액션(Action)으로 나누어진다. 둘을 연결하면 When - Do, 즉 특정한 때가 되면, 지정한 작업을 하도록 명령하는 것이 일반적인 스크립팅의 패턴이다.

[그림] 스크립팅의 구조

언리얼 엔진은 스크립팅 로직 전개를 위해 대표적으로 아래의 두 가지 이벤트를 제공한다.

- Begin Play 이벤트 : 액터가 월드에서 처음 동작할 때 발생하는 이벤트다. 액터가 본격적으로 레벨에서 뛰어 놀기 전, 기본 세팅을 정리할 때 사용한다.
- Tick 이벤트 : 컴퓨터가 이미지를 그릴 때마다 발생하는 이벤트다. 이 이벤트는 빈도가 굉장히 잦은 이벤트라 주로 액터의 움직임에 관련된 명령에 사용한다.

이 외에도 언리얼 엔진에는 여러 이벤트가 있으며, 사용자가 직접 제작할 수도 있다. 이번 글에는 위의 두 이벤트를 사용해 간단한 스크립팅을 구성해보겠다.


Begin Play 이벤트

Begin Play 이벤트는 액터가 게임에서 처음 실행될 때 발생하는 이벤트다. 이 이벤트를 사용해 액터 실행될 때 간단한 문장을 화면에 출력해보자. 블루프린트 스크립팅은 블루프린트의 이벤트 그래프에서 제작 가능하다. BP_Fountain 블루프린트를 더블 클릭하고 블루프린트 에디터를 연 후에, 이벤트 윈도우로 이동한다. 이 이벤트 윈도우가 게임 플레이시 레벨에서 행동할 액터의 로직을 설계하는 공간이다. ( 이벤트 그래프는 왼쪽의 내 블루프린트 윈도우에서 이벤트 클릭을 통해도 열 수 있다. )

[그림] 이벤트 윈도우

이벤트 윈도우를 보면 반투명으로 어둡게 생긴 세 개의 붉은 색으로 표현된 노드가 보이는데, 붉은 색으로 된 노드는 이벤트를 의미한다. 언리얼 엔진은 블루프린트를 처음 생성할 때 자주 사용하는 이벤트를 보여주기 위해, 일부로 반투명하게 처리해놓았으며, 아직은 비활성 상태다.  Begin Play 이벤트가 발생하면 간단한 문장을 화면에 출력하기로 했으므로, 화면에 출력하는 Print String 명령을 꺼내보자. 이를 위해 이벤트 그래프의 Begin Play 오른쪽에 비어 있는 작업 공간을 우클릭하여 액터가 사용할 수 있는 명령을 살펴보자. 하지만 명령 목록을 클릭해 뒤져보면 액터에서 사용할 수 있는 명령이 굉장히 많아 일일이 뒤져가며 찾기에는 무리가 있다.

[그림] 액터가 사용할 수 있는 명령어들

일일이 뒤지는 대신에 아래와 같이 검색을 활용하면 사용자가 원하는 명령을 쉽게 찾을 수 있다. 상단의 검색 메뉴에서 print라고 검색하면 필터링된 Print String 명령을 쉽게 발견할 수 있는데, 이를 선택해 작업 공간에 명령을 불러들이자.

 
[그림] Print String 명령의 검색과 사용

화면에 명령을 배치한 것만으로는 컴퓨터는 아무 일도 하지 않는다. 컴퓨터가 명령을 실행하게 만들기 위해서는 반드시 이벤트 그래프와  명령을 연결시켜 When-Do 조합을 만들어야 한다. 연결을 위해 이벤트와 명령어 노드 상단에 있는 실행 흐름(Execution Flow)을 연결한다. 연결이 되면 흐릿했던 Begin Play가 밝아지고 액터에게 비로소 명령을 내릴 수 있게 된다.

[그림] 이벤트와 명령의 연결

Print String 명령 노드는 왼쪽의 In String이라는 이름의 Pin을 통해 이 명령을 실행하는데 참고할 보조 데이터를 입력받도록 설계되어 있다. 이 핀은 우리가 화면에 출력할 문장을 입력하는 곳이다.  
여기에 "Hello" 대신 사용자가 좋아하는 문장을 넣어본다. 나는 "In the Heroes of the Storm!"으로 변경하겠다. 로직이 완성되면 툴바에 있는 컴파일 버튼을 누르자. 참고로 컴파일(Compile)이란 사용자가 만든 로직이 컴퓨터가 이해할 수 있게 잘 구성되었는지 검증하고, 이를 기계가 이해할 수 있는 언어로 번역(interprete)하는 작업을 의미한다. 사용자의 로직에 문제가 없다면 컴파일 결과는 아래 그림처럼 녹색으로 뜨게 된다. ( 굳이 "Hello World!"를 입력하고 싶은 분들은 그렇게 하셔도 된다. )

[그림] 컴파일 결과 

이제 플레이 버튼을 눌러 첫 스크립트를 실행해 보자. 시작하자마자 핀에 입력한 문장이 화면에 뜨고, 잠시 뒤에 사라지는 것을 확인할 수 있다. 잘 작동하는지 확인하자.

[그림] 로직을 실행한 결과 화면 

이제 다시 블루프린트로 돌아가 이번에는 더 이상 화면에 글자가 출력이 되지 않도록 실행 흐름을 끊어보겠다. Begin Play 이벤트와 Print String 사이에 연결된 선을 끊으면 이벤트 그래프 공간에 명령은 존재하지만 액터는 더 이상 이 명령을 실행하지 않는다.  끊는 방법은 이전 머티리얼 에디터에서 사용한 방법과 동일하다. Alt 키를 누른 상태에서 연결 지점이나 연결 선을 클릭하면 끊어진다. 
블루프린트 스크립팅을 구성할 때에는 명령 노드에 대해 추가적인 설명을 넣을 수 있다. Print String 노드를 선택한 후 키보드 C (Comment) 키를 누르면 아래와 같이 설명을 남길 수 있다. 

[그림] 로직의 해제와 명령에 대한 코멘트


Tick 이벤트 

이번에는 틱 이벤트를 사용해 분수대를 회전시켜보겠다. 아래 그림과 같이 애니메이션을 이루는 각 이미지를 프레임(Frame)이라고 하는데, 게임도 우리 눈에는 부드럽게 움직이는 것처럼 보이지만 결국 여러 프레임 이미지들이 모니터에서 하나씩 빠르게 재생된 결과물일 뿐이다. 

[그림] 애니메이션 프레임의 예시

Tick 이벤트는 언리얼 엔진이 프레임을 만들 때 마다 발생시키는 이벤트다. 사용자가 플레이 버튼을 누른 후 가만히 있어도 컴퓨터는 자신이 그릴 수 있는 최대의 속도로 이미지를 계속 생산해내고 있다. 이는 즉 정지해 있는 상태라도 레벨에 배치된 모든 액터에는 Tick 이벤트가 발생하고 있다는 것을 의미한다. 제작한 분수대의 Tick 이벤트마다 약간의 회전을 가미해주면 우리의 분수대는 애니메이션과 같이 부드러운 회전 움직임을 가지게 된다. 
이를 스크립트 로직으로 구현해보자. 액터를 현재 위치에서 사용자가 지정한 도(Degree)만큼 추가로 회전시키는 명령은 AddActorLocalRotation이다. 이를 Tick 이벤트에 연결하고 명령의 Delta Rotation 핀의 Z에 프레임마다 추가로 회전시킬 값을 입력하자. 아래 그림처럼 10을 기재하면 이제 이 액터는 매 프레임마다 10도씩 Z축을 기준으로 회전하는 맷돌과 같은 움직임을 가지게 된다.

[그림] 최종 회전 로직과 결과 

참고로 게임이 원활하게 동작하기 위해서는 보통 60프레임을 맞춰야 한다고 이야기를 한다. 현재 컨텐츠가 60프레임으로 동작하는 경우 프레임당 평균 0.01667초가 소비되며 시공의 분수대는 1초에 600도를 회전하는 움직임을 가지게 된다.


레퍼런스(Reference)

분수대 회전을 확인하면 이번에는 분수대가 아닌 물을 회전시켜보자. 액터를 회전하는 명령을 끊고, 대신 물을 회전시키는 로직을 넣는다. 액터는 고정된 상태에서 물이 회전해야 하기 때문에, 액터의 회전이 아닌 물을 담당하는 스태틱 메시 컴포넌트에 회전 명령을 주어야 한다. 이를 위해 물을 담당하는 FountainWater 스태틱 메시 액터에 명령을 주어야 하는데 FountainWater 스태틱 메시를 작업공간으로 드래그 해본다. 그러면 아래의 그림과 같은 작은 노드가 생성된다. 이것을 레퍼런스(Reference)라고 한다. 

[그림] 스태틱 메시 컴포넌트에 대한 레퍼런스의 생성

레퍼런스란 이미 만들어진 물체에 명령을 주기 위한 바로가기 링크와 같은 개념이다. 이 링크를 사용해 이미 만들어진 물체에 명령을 줄 수 있게 된다. 레퍼런스의 핀으로부터 선을 드래그한 후에 놓으면 현재 분수대 액터가 아닌 FountainWater 스태틱 메시 컴포넌트에 전달할 명령 목록이 뜬다. 여기서 AddLocalRotation 명령을 사용하면 컴포넌트의 회전을 기능을 줄 수 있게된다. 물의 회전은 5만 입력했다. 

[그림] 레퍼런스를 사용해 스태틱 메시 컴포넌트에 회전을 주는 명령

이를 실행하면 아래 그림과 같이 액터는 고정 시킨 상태에서 물만 회전하게 된다. 

[그림] 블루프린트를 적용한 최종 결과 화면



2017년 2월 13일 월요일

[언리얼4 RPG제작 2-1] 블루프린트 시스템

Part2에서는 언리얼 엔진에서 게임을 구성하는 요소들에 대해 기록할 예정이다.
이번 파트부터는 캐릭터가 등장하면서 점점 RPG스럽게 프로젝트가 업그레이드 될 예정이다. 그래서 RPG 프로젝트답게 중세 분위기에서 작업을 진행해보겠다. 시작하기 전에 아래 링크에 접속해 이번 파트에서 사용할 리소스를 다운 받는다.

리소스 링크 : http://bit.ly/bp_rpgasset2

다운을 받아 압축을 풀면 하위에 있는 AssetProject 폴더에 별도의 언리얼 프로젝트가 있음을 확인할 수 있다. 폴더에 있는 Lesson2Asset.uproject 파일을 더블클릭하여 준비된 언리얼 프로젝트를 띄워보자. 그러면 기존에 작업하던 프로젝트와 새로운 프로젝트 두 개의 언리얼 에디터가 뜬다.

[그림] 두 개의 언리얼 프로젝트


이주(Migration) 기능

진행을 위해 다운받은 새로운 프로젝트에서 사용할 애셋을 복사해옵시다. 새로운 프로젝트에 있는 Lesson2 폴더가 새롭게 사용할 리소스들 인데, 이를 기존에 작업던 프로젝트로 옮겨오기 위해 우클릭하고 애셋 액션에서 이주(Migration)를 선택하자.

[그림] 이주 메뉴

이주는 현재 프로젝트에서 사용하는 리소스를 다른 프로젝트로 옮길 때 사용하는 기능이다. 이주 기능은 단순히 선택한 리소스를 복사하지 않고, 현재 리소스에 연관된 다른 리소스까지 모두 모아 사용자가 지정한 다른 프로젝트로 옮겨준다. 주의할 점은 이주 대상을 지정할 때에는 옮길 프로젝트의 대표 폴더를 선택하는 것이 아닌 그 아래에 있는 Content 폴더를 선택해야 한다. Content 폴더를 선택하여 오른쪽 하단에 이주가 성공적으로 끝났다는 메시지가 뜨면 이제 작업 중인 프로젝트로 돌아가자. 작업 프로젝트의 콘텐츠 브라우저에서 Lesson2와 그 하단의 폴더들이 잘 들어왔는지 확인되면, 이제 리소스 프로젝트는 역할을 다 했으니 종료한다.

[그림] 리소스의 이주 결과


블루프린트(Blueprint)

이제 준비가 되었으니 시작하겠다. 이번 에는 언리얼 엔진의 핵심 기능인 블루프린트(Blueprint)에 대해 정리하겠다. 언리얼 엔진의 블루프린트는 복잡한 액터를 설계하도록 고안된 설계 시스템을 의미한다. 지금까지 사용한 액터는 하나의 단순한 기능만 가진 액터였습다. 스태틱 메시 리소스를 드래그해 배치해왔던 스태틱 메시 액터는 하나의 스태틱 메시 리소스만 사용하는 액터다. 아래 그림과 같이 물, 라이트, 돌, 풀 등의 다양한 요소를 가진 하나의 분수대를 만든다고 가정하자.

 [그림] 조금 복잡한(?) 분수대 예시

위의 분수대에는 분수대, 물, 풀, 돌, 라이트의 총 다섯 개 액터가 사용되었다. 하지만 배경에서 이러한 분수대를 자주 사용해야 한다고 가정하면, 분수대를 10개만 배치해도 50개의 액터를 배치해야 한다. 하지만 5개의 액터가 가지는 기능을 모두 조합해 하나의 액터로 만들 수 있다면 어떨까? 하나의 분수대 역할을 수행하는 액터를 만들어 놓으면 50개의 액터를 조정할 필요 없이 레벨에는 10개의 액터만 배치하면 된다. 차후에 분수대의 기획이나 아트가 변경되면 어떻게 될까? 전자의 경우 50개를 보면서 일일히 고쳐줘야 하는 반면, 후자는 액터의 조합 설정만 변경하면 연관된 액터들을 모두 자동으로 업데이트된다. 이렇게 액터의 배치와 관리를 편리하게 하기 위해 언리얼 엔진이 제공하는 설계 기능이 블루프린트(Blueprint)다.

[그림] 블루프린트의 개념

그러면 새로운 맵에서 직접 블루프린트를 제작해보자. [파일 > 새 레벨] 메뉴를 선택해 Default 템플릿을 사용해 새로운 레벨을 생성하고 기본으로 주어지는 Floor 액터를 제거하고. 대신 콘텐츠 브라우저 [ Lesson2 > Floor ] 폴더에 있는 SM_MergedFloorBig 스태틱메시를 배치하여 분위기를 바꿔보자. 시작 지점이 새로운 바닥의 가운데로 오도록 디테일에서 좌표를 직접 입력해 옮겨본다. 나는 좌표를 ( -1500, 1500, -113)로 하였다. 이제 새로운 이름으로 레벨을 저장하고 플레이를 누르면 중세풍의 돌 바닥에서 여러분들이 돌아다닐 수 있게 된다.

[그림] 기본 바닥의 생성

이번에는 Fountain 폴더로 가서 준비된 분수대와 물을 배치한다. 먼저 분수대를 드래그하여 배치한 후 물도 드래그하여 추가로 배치한다. 물의 위치를 잡기 편하게 하기 위해 배치된 물 액터를 분수대 액터에 드래그해 분수대 액터의 자식으로 계층 구조를 들어보자. 일단 자식으로 계층 구조를 만든 후, 아래와 같이 X와 Y값은 0으로 고정하고 Z축으로만 136cm 올려주면 그림과 같이 물이 흐르는 분수대가 완성된다.

[그림] 기본 분수대의 설정

이번에는 동일한 기능을 가진 분수대 블루프린트를 제작해보자. 콘텐츠 브라우저에서 블루프린트를 보관할 Blueprints라는 폴더를 생성한다. 생성한 폴더를 선택하고 콘텐츠 브라우저의 신규 추가와 블루프린트 클래스 메뉴를 선택하면 부모 클래스 선택이라는 다이얼로그가 뜬다. 잠깐 여기서 부모 클래스란 무엇일까? 어떤 물체를 제작하기 위해 고안한 설계도인 블루프린트와 유사한 개념을 프로그래밍 용어로는 클래스(Class)라고도 한다. 부모 클래스를 선택한다는 의미는 목표로 하는 물체를 쉽게 만들기 위해 누군가에 의해 미리 만들어 둔 기능을 활용하고, 거기에 없는 기능을 추가해 제작한다는 것을 의미한다.  ( 왜 언리얼 엔진은 유사한 블루프린트와 클래스라는 용어를 혼용해 사용할까요? 둘의 구조와 용도가 사실 미묘하게 다른데, 중요한건 프로그래머가 아니라면 앞으로 클래스라는 단어를 사용할 일이 없으니 크게 집착하지 않아도 된다. )

 [그림] 부모 클래스와 블루프린트의 상관 관계

아무튼, 가장 상단의 액터를 선택하면, 액터를 설계할 수 있는 블루프린트 리소스가 생성되는데, 이 블루프린트의 이름을 BP_Fountain이라고 제작하자. 리소스 이름은 차후에 F2키를 눌러서 변경이 가능하다.

[그림] 완성된 블루프린트


컴포넌트(Component)

이를 더블클릭하면 블루프린트 에디터가 뜬다. 블루프린트 에디터가 뜨면 텅 빈 것을 볼 수 있는데, 이 액터에 분수대가 되기 위해 필요한 기능을 부여해주어야 한다. 이를 위해서 알아야 할 개념이 컴포넌트(Component)다.
언리얼 엔진은 게임 제작에 필요한 정말 많은 기능을 엔진을 제작한 엔지니어들이 오랜 기간 동안 만들어왔는데, 이번에 만들 액터를 제작하는데 이들을 쓰기 위해 표준 규격으로 정리하고 종류별로 분류해놓았다. 이렇게 액터에 사용할 수 있게 규격화된 기능 모듈을 컴포넌트라고 한다. '컴포넌트 추가' 버튼을 눌러 보이는 여러 컴포넌트 중에서 스태틱 메시를 보여주는 모듈은 스태틱 메시 컴포넌트다. 컴포넌트 추가버튼을 누른 후 스태틱 메시 컴포넌트를 추가하고 이름을 FountainBody라고 짓는다.

[그림] 스태틱 메시 컴포넌트의 추가

추가한 스태틱 메시 컴포넌트를 선택하면 디테일 윈도우에서 스태틱 메시를 지정해야 한다. SM_Plains_Castle_Fountain_01 스태틱 메시를 선택해 스태틱 메시 컴포넌트의 세팅을 완료하자. 항상 블루프린트를 작업하고 마무리할 때에는 툴바에 있는 컴파일, 저장버튼을 꼭 눌러주자.

[그림] 스태틱 메시 컴포넌트의 설정 결과


루트 컴포넌트(Root Component)

블루프린트에서 컴포넌트의 최상단에 위치해 액터를 대표하는 컴포넌트를 루트 컴포넌트(Root Component)라고 한다. 액터를 제작할 때에는 반드시 하나의 루트 컴포넌트가 필요하다. 그래서 블루프린트를 처음 만들 때에는 아무 기능이 없는 기본 씬루트컴포넌트가 설정되어 있다. 여기엔 분수대 액터를 대표할 스태틱 메시 컴포넌트를 하나 제작했으니, 이를 루트 컴포넌트로 대체하자. 루트 컴포넌트로 대체하는 방법은 FountainBody 컴포넌트를 씬루트컴포넌트로 드래그하면 된다. 이제 분수대에 추가로 물을 표현하기 위해 새로운 스태틱 메시 컴포넌트를 추가한다. 추가된 컴포넌트는 자식으로 붙음을 확인할 수 있다. 액터에 루트 컴포넌트는 하나만 존재할 수 있으며, 이후에 생성되는 컴포넌트는 모두 루트의 자식으로 붙게되면서 부모로부터 상대적인 트랜스폼을 가지게 된다. 새롭게 추가한 컴포넌트의 이름을 FountainWater로 변경하고, 새로운 스태틱 메시의 트랜스폼 값을 앞서서 진행한 것처럼 Z값만 136으로 입력하면 그림과 같이 물이 나오는 분수대 액터가 완성된다.

[그림] 물 스태틱 메시의 설정 결과

다시 툴바에서 컴파일, 저장 버튼을 누른 후 레벨로 돌아가 지금 완성한 블루프린트를 드래그해 배치해본다. 앞서서 제작한 분수대는 액터를 2개 사용한 반면, 블루프린트를 통해 만든 분수대는 하나의 액터에서 일괄 관리할 수 있게 되었다.

[그림] 두 분수대의 비교


블루프린트 제작 시 주의할 점들

아래는 블루프린트 사용시 주의할 점들이다.
- 블루프린트를 처음 열 때에는 컴포넌트의 조립 결과를 시각적으로 확인할 수 있는 뷰포트 창이 열린다. 하지만 두 번째부터는 로직을 넣는 이벤트 창이 열린다. 추가적으로 컴포넌트를 조립하고 확인하고 싶으면 뷰포트 창으로 이동하면 된다.

[그림] 뷰포트 창과 이벤트 창

- 블루프린트를 생성한 후 더블 클릭해 에디터를 연 다음 아무것도 하지 않고 닫은 후, 다시 더블클릭하여 열면 아래 그림과 같이 기본 값만 보이는 간략 버젼으로 뜬다. 이 때 당황하지 말고 상단의 "풀 블루프린트 에디터 열기"를 클릭하면 원래대로 들어온다.

[그림] 풀 블루프린트 에디터 열기

- 가끔 블루프린트를 더블 클릭했는데, 아래와 같은 현상이 발생할 때가 있다. 당황하지 말고 창에서 '클래스 디폴트'를 선택한 후, 다시 '풀 블루프린트 에디터 열기'를 선택하면 된다.

[그림] 비어있는 블루프린트가 뜨는 경우


블루프린트 제작 마무리

다시 블루프린트로 돌아가 Point Light 컴포넌트 및 다른 Static Mesh 컴포넌트를 추가해 분수대를 더 꾸며보자. 아래 그림은 SM_Plains_Fern02 스태틱 메시와 SM_Plains_LargeRock_Pile01 스태틱 메시를 추가한 결과다.

[그림] 포인트 라이트 컴포넌트와 스태틱 메시를 추가한 결과 화면

컴파일, 저장 버튼을 누르고 레벨로 돌아가면 별도의 부가적인 작업 없이도 아래 그림과 같이 블루프린트로 드래그한 액터에 변경사항이 자동으로 업그레이드 된 것을 확인할 수 있다.

[그림] 업그레이드 된 분수대 액터의 최종 결과



참고자료의 출처: http://cafe.naver.com/unrealenginekr/13118

2017년 2월 12일 일요일

[언리얼4 RPG제작 1-10] 머티리얼 인스턴스

이번 에는 머티리얼을 효과적으로 관리하는 방법에 대해 살펴보겠다. 지난 글에 만든 머티리얼과 내용은 동일하지만, 다른 색상과 눈빛(!)을 가진 재질을 만들고 싶다면 예전에 한 방식대로 Ctrl+W키를 눌러 복제하고 여기서 색상, 텍스쳐 노드의 정보를 변경하면 1차적으로 해결은 가능하다. 하지만 기존에 만든 머티리얼을 기능을 추가해 더 복잡하게 업그레이드 했다면, 복제된 머티리얼도 일일히 변경해야 하는 번거로운 작업이 발생하게 된다.
이러한 노가다(?)를 미연에 방지하기 위해 언리얼 엔진에서는 머티리얼 인스턴스라는 시스템을 제공한다. 머티리얼 인스턴스는 기본 머티리얼에 사용했던 색상, 숫자, 텍스쳐 노드를 파라미터 노드로 대체해, 관리를 2원화 하는 방식이다. 머티리얼 원본 제작자는 기본 머티리얼의 설계에 집중하고, 이를 사용하는 작업자는 원본 제작자가 지정한 파라미터 값만 변경하면 내부 머티리얼이 어떻게 연결되 제작되는지 몰라도 다양한 효과를 표현할 수 있게 된다. 사전에 설명이 길었는데 직접 머티리얼 인스턴스를 제작해보자.

먼저 지난 번에 작업한 M_ToyCow 머티리얼을 열고 배경 색상에 사용했던 노드를 선택하자. 노드를 오른쪽 클릭하면 상단에 파라미터로 변환이라는 메뉴가 보인다. 이를 선택한다.
[그림] 파라미터로 변환 메뉴

파라미터로 변환 메뉴를 누르면 큼지막하게 노드로 변경되는데, 이 노드가 앞으로 작업자들이 값을 변경할 수 있는 노드가 된다. 작업자들이 알아볼 수 있도록 이름을 배경색상으로 바꾸고 그룹을 몸통이라는 이름으로 지정하자. 그룹을 지정할 때에는 그냥 이름을 드롭다운 창에서 바로 입력하면 자동으로 생성된다.  ( 언리얼 엔진에서는 파일에 해당하는 리소스 이름을 제외한 내부 로직에서 한글을 마음대로 사용할 수 있다. 편한대로 영문 혹은 한글을 병행해 사용하면 된다. 경험상 한글은 파일 이름을 지정할 때에만 주의하시면 된다.  )

[그림] 파라미터의 설정

이렇게 머티리얼에 파라미터 노드를 추가하면 머티리얼 인스턴스에서는 이 파라미터를 사용해 다양한 머티리얼로 변화시킬 수 있다. 콘텐츠 브라우저로 가서 제작한 M_ToyCow 머티리얼을 우클릭하고 머티리얼 인스턴스 생성 버튼을 누르고 M_ToyCow_Inst1으로 저장한다.

[그림] 머티리얼 인스턴스의 생성 메뉴

메뉴를 눌러 생성된 M_ToyCow_Inst1 머티리얼 인스턴스를 더블 클릭하면 복잡한 노드의 구성 없이 우리가 지정한 파라미터 값만 작업자가 체크해서 수정할 수 있도록 별도의 인터페이스가 제공된다.

[그림] 머티리얼 인스턴스 설정 화면

비활성화되어 있는 기본 색상 파라미터를 체크하고 다른 색상으로 설정하면 다른 느낌을 주는 머티리얼을 쉽게 제작할 수 있다. SM_ToyCow 스태틱메시를 배치해 스태틱 메시 액터를 하나 더 추가하고, 새롭게 생성된 머티리얼 인스턴스를 배치하자.

[그림] 머티리얼 인스턴스를 새로운 스태틱 메시 액터에 적용한 결과

같은 방식으로 입 주위의 색상과 줄무늬 텍스쳐, 안광의 색상 및 크기도 파라미터화 시켜 머티리얼 인스턴스를 조절해보자. 파라미터화 시킨 원본 머티리얼 구성은 다음과 같다. 참고로 곱셈노드에는 '1'키를 눌러 스칼라노드를 추가로 연결한 후 이를 파라미터화 해야 한다. 그룹은 한번 수동으로 설정하면 다음 부터는 드롭다운에서 선택이 가능하다.

[그림] 파라미터화한 원본 머티리얼 설계

머티리얼 인스턴스 시스템의 장점은 설계자와 작업자가 완벽하게 분리되어 있기 때문에 기존에 제작한 머티리얼 인스턴스는 원본 머티리얼의 변화를 자동적으로 반영해준다. M_ToyCow_Inst1 머티리얼을 열면 아래와 같이 자동으로 파라미터들이 변화된 것을 확인할 수 있다. 이 값들을 변경해 보다 다양한 장난감 소를 표현해보자.

[그림] 자동으로 변경된 머티리얼 인스턴스 설정


[텍스쳐의 설정]

이번 글의 주제인 머티리얼 인스턴스와는 큰 관련이 없지만, 머티리얼의 완성도가 있게 마무리하기 위해 텍스쳐 설정에 대해서도 작성하고자 한다. 텍스쳐의 용도는 T_ToyCow_C와 같이 데이터 용도로 사용하는 텍스쳐와 풀 나무같이 색상 표현을 위해 사용하는 텍스쳐의 두 가지로 나뉘게 된다. 대부분의 게임 엔진에서 용도에 따라 텍스쳐를 구분하는 것이 중요한데, 이유는 감마 보정(Gamma Correction)이라는 설정때문이다. 머티리얼 에디터에서 색상을 계산할 때는 RGB채널값이 각각 0부터 1까지 균등하다는 설정에 기반하고 있다. 하지만 인간의 눈은 컴퓨터처럼 각 채널 별 값에 따라 균등하게 반응하지 않는다. 실제로 인간의 눈은 녹색에 대해서 좀 더 민감하게 반응하는데, 게다가 대표적인 색상 출력기기인 모니터의 경우 발광한다는 속성으로 인해 비선형적으로 처리하도록 설계되어 있다. 예를 들자면 아래 그림의 파란색 라인이 이상적인 색상 정보라면, 모니터는 위에서 언급한 다양한 이유로 빨간색 커브를 사용해 색을 출력하도록 설계되어 있다. 그래서 파란색 라인을 따르는 정보로 색상을 저장해 바로 모니터에 내보내면 실제 모니터에서는 첫 번째 꽃처럼 어둡게 표현이 된다. 이 문제를 해결하는 좋은 방법은 이미지를 저장할 때 두 번째 꽃과 같이 아예 노란색 라인을 따르는 비선형으로 색상값을 변환해 저장해버리는 것이다. 이렇게 되면 이 이미지는 자동으로 모니터가 사용하는 빨간 라인 수치와 상쇄되어 우리가 딱히 아무짓을 안해도 세 번째 꽃과 같은 올바른 결과가 모니터에 표시된다.

[그림] 감마 보정(Gamma Correction)의 개념

이렇게 비선형적으로 색상을 저장하는 방법은 색상을 다루는 카메라 및 프로그램 제작사 마다 여러가지가 있는데 언리얼 엔진에서 비주얼한 이미지를 저장할 때는 sRGB라는 모델을 사용한다. 따라서 언리얼 엔진에서 비주얼한 텍스쳐 설정에는 항상 sRGB 옵션이 켜져 있다.

[그림] 비주얼한 텍스쳐 설정에 항상 켜져 있는 sRGB 옵션

하지만 앞서 사용한 T_ToyCow_C이미지의 경우 비주얼한 용도와는 전혀 상관 없이 Lerp 함수를 계산하는데에만 사용이 된다. 이러한 경우에는 굳이 sRGB를 사용해 데이터를 왜곡 시킬 필요가 전혀 없다. 이를 위해 언리얼이 제공하는 옵션이 Mask 설정이다. 텍스쳐 메뉴에서 이를 변경하면 자동으로 sRGB 옵션이 변경되는 것을 볼 수 있다.

[그림] 텍스쳐의 설정 변경

하지만 머티리얼에서 처음 텍스쳐 노드를 사용할 때 sRGB로 변환된 비주얼한 텍스쳐를 쓴다고 했기 때문에, 텍스쳐 설정을 변경하고 머티리얼 에디터로 돌아가면 텍스쳐 노드에 에러가 나있음을 확인할 수 있다.  이는 텍스쳐 타입이 Color로 지정되어 있기 때문에 그렇다. 텍스쳐 노드를 선택하고 용도를 Mask로 변경하면 해당 에러를 수정할 수 있으며, 이제는 보다 데이터의 왜곡 없이 정확하게 영역을 구분할 수 있도록 머티리얼이 업그레이드되었다.

[그림] 텍스쳐 노드의 타입 변경

컴퓨터 그래픽에서는 데이터로 사용하는 이미지 중 대표적인 것에 노멀맵(Normal Map)이있다. 이는 텍스쳐에 매핑된는 각 픽셀 영역에서 노멀(Normal)이라 불리는 면이 향하는 방향 정보를 텍스쳐 데이터에 담긴 데이터로 변환해 실제로 평평한 지형이 울퉁불퉁하게 빛과 반응하도록 처리하는 대표적인 기법이다. 컴퓨터 그래픽 처리의 핵심을 담당하는 그래픽 카드 GPU는 매우 빠르게 텍스쳐를 처리할 수 있기 때문에 이렇게 이미지에 데이터를 담아 보내도록 고안한 것이다. 아래 이미지는 노멀맵을 사용할 때와 안할 때의 차이를 보여주는 예시다.

[그림] 노멀맵의 사용 전후 비교. 아래가 노멀맵을 사용한 결과

이제 장난감소 머티리얼에 T_ToyCow_N 텍스쳐를 추가해 머티리얼을 최종 완성하다. 노멀맵은 언리얼 엔진이 ( 100%는 완벽하지 않지만 ) 자동으로 파악해 노멀맵으로 설정하며, 이 텍스쳐는 노멀 출력핀에 연결하면 된다. 그리고 위의 설명을 이해했다면 당연한 이야기겠지만, 노멀맵이라는 것은 비주얼이 아니라 데이터이므로 모든 노멀맵 텍스쳐 설정에 sRGB 옵션은 항상 꺼져 있다.

[그림] 노멀맵을 연결한 결과. 미리보기 결과가 울퉁불퉁하게 변한 것을 볼 수 있다.



참고자료의 출처: http://cafe.naver.com/unrealenginekr/13056