게임을 만든다는 것은 조작에 따라 서로 다른 이미지를 보여주는 소프트웨어를 만드는 일이다. 이 소프트웨어가 원하는대로 실행하기 위해 우리는 컴퓨터에게 명령을 내리게 될텐데, 기획 의도대로 소프트웨어가 동작하도록 컴퓨터 명령을 설계하는 작업을 프로그래밍(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 명령을 쉽게 발견할 수 있는데, 이를 선택해 작업 공간에 명령을 불러들이자.
화면에 명령을 배치한 것만으로는 컴퓨터는 아무 일도 하지 않는다. 컴퓨터가 명령을 실행하게 만들기 위해서는 반드시 이벤트 그래프와 명령을 연결시켜 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만 입력했다.
[그림] 레퍼런스를 사용해 스태틱 메시 컴포넌트에 회전을 주는 명령
이를 실행하면 아래 그림과 같이 액터는 고정 시킨 상태에서 물만 회전하게 된다.
[그림] 블루프린트를 적용한 최종 결과 화면
댓글 없음:
댓글 쓰기