No.7 Unity 3D Platform Tutorial "The GUI #2"
씬 세팅하기
첫 단계는 새로운 빈 씬을 생성하는 것입니다.
ㅁ Mac에서 CMD + N 또는 PC에선 Ctrl+N을 눌러 씬을 하나 만들고, CMD+S 또는 Ctrl+S를 눌러 저장하십시오.
ㅁ StartMenu라 이름 짓습니다. 유니티는 자동으로 카메라를 추가해 주지만, 현재 시점에서는 카메라에게 보일만 한 게 없습니다.
이제 우리는 새 GUI 시스템을 이용해 메뉴를 만들 것입니다:
ㅁ Project Pane으로 가서 빈 Javascript 파일을 만듭니다.
ㅁ StartMenuGUI라고 이름 짓고 에디터를 이용해 파일을 엽니다.
먼저, 우리는 유니티 스크립트 명령을 추가할 것입니다. 명령들은 유니티에게 스크립트에 대한 정보나 추가적인 지시등을 보내주는 명령어들입니다. 이 명령어들은 Javascript 또는 그러한 언어의 한 부분은 아니지만 유니티 자체를 대상으로 하고 있습니다. 부록에서 완전한 스크립트 코드를 찾아볼 수 있습니다.
현 상황에선, 우리는 유니티가 에디터내의 스크립트를 실행하여 프로젝트를 매번 멈추거나 다시 실행하지 않고 결과를 바로 볼 수 있도록 원하기 때문에:
==============================================================================
// 스크립트가 편집 모드에서도 실행되도록 한다
@script ExecuteInEditMode()
==============================================================================
우리는 LerpzTutorialSkin 자산으로의 링크가 필요하기 때문에, 코드의 첫 줄은 이러할 것입니다:
==============================================================================
var gSkin : GUISkin;
==============================================================================
우리는 배경막을 위해 Texture2D 객체가 필요합니다. (우리는 배경막 이미지를 이 객체의 Inspector 에 드래그 할 것입니다.)
==============================================================================
var backdrop : Texture2D; // 우리의 배경막 이미지는 여기에 들어갑니다.
==============================================================================
우리는 또한 플레이어가 "Play"버튼을 클릭하였을 때 "Loading..." 메시지를 표시하고 싶기 때문에, 우리는 이를 다뤄줄 플래그(Flag)가 필요합니다.
==============================================================================
private var isLoading = false; // 참이면, "Loading..." 메시지를 표시할 것입니다.
==============================================================================
마지막으로 OnGUI함수 자체에 착수합니다.
==============================================================================
function OnGUI()
{
if (gSkin)
GUI.skin = gSkin;
else
Debug.Log("StartMenuGUI: GUI Skin object missing!");
==============================================================================
위의 코드는 유효한 GUI 스킨 객체로의 링크가 있는지를 체크합니다. 링크가 없는 경우엔 Debug.Log() 함수가 에러 메시지를 표시할 것입니다. (외부 링크 또는 데이터를 이러한 방식으로 정상테스트(sanity-check)하여 디버깅을 좀 더 쉽게 하는 것은 코딩하는데 있어 매우 좋은 습관입니다.)
배경막
배경막(Backdrop)의 이미지는 우리의 배경(Background)이미지를 요소의 배경으로 사용하기 위한 GUI.Label의 요소 세트입니다. 그렇기 때문에 배경막 이미지에는 텍스트가 없고, 화면의 크기에 따라 언제나 조정되도록 되어있어 배경이 화면에 꽉 차도록 해줍니다.
==============================================================================
var backgroundStyle : GUIStyle = new GUIStyle();
backgroundStyle.normal.background = backdrop;
GUI.Label ( Rect( (Screen.width - (Screen.height * 2)) * 0.75, 0, Screen.height * 2, Screen.height), "", backgroundStyle);
==============================================================================
먼저, 우리는 기본 GUI 스킨 스타일을 오버라이드 할 때 사용할 새 GUIStyle 객체를 정의하여야합니다. 이 경우, 우리는 배경막 이미지를 사용하기 위해서 "normal.background" 스타일 요소를 바꾸는 것입니다.
GUI.Label() 함수는 Rect 객체를 갖습니다. 이 직사각형의 크기는 화면의 크기에서 비롯되어 이미지가 언제나 화면을 채우도록 합니다. 이미지의 화면 비율 또한 계산에 포함되어, 이미지가 일그러짐 없이 잘리거나 크기가 변경될 수 있도록 합니다.
다음은 타이틀 텍스트를 건드려 봅시다. 이에 대한 스크립트를 작성하기 전에, 우리의 GUI 스킨을 살펴보고 약간의 수정을 가해야합니다:
우리의 메뉴는 기본 폰트로 정의된 LerpzTutorialSkin 에셋을 사용하고 있습니다. 현재 시점에선, 이 기본 폰트스타일은 큰 게임 타이틀의 텍스트를 표시하기에는 적합하지 않기 때문에, 우리는 이 스킨에 mainMenuTitle이라고 이름 붙여진 새로운 사용자 지정 GUI 스타일을 추가할 것입니다.
ㅁ Project Pane으로 가서 LerpzTutorialSkin을 클릭하여 Inspector에 내용을 불러옵니다.
이제 사용자 지정 스타일을 GUI 스킨에 추가할 것입니다:
GUISkin 객체에 사용자 지정 스타일을 정의하기
ㅁ "Custom Styles"를 열고 "Size"의 값이 "1"로 설정되어있는지 확인합니다. 확인한 후에 설정을 살펴보면 "Element 0" 입력 값이 보일 것입니다.
ㅁ 위의 그림처럼 "Element 0"을 엽니다. 특별히 텍스트의 색깔을 보인 것과 같이 갈색과 오렌지풍의 색으로 설정합니다. (스크린샷에 보이지 않은 다른 요소들에 대해서는 걱정하지 마십시오: 그 부분 들은 그대로 나두어도 좋습니다.)
마지막으로, 스크립트에 남은 코드를 추가합니다.
==============================================================================
GUI.Label ( Rect( (Screen.width/2)-197, 50, 400, 100), "Lerpz Escapes", "mainMenuTitle");
==============================================================================
☆ 참고
GUI 스타일의 이름들은 스크립트 상에서 접근하려고 할 때엔 대소문자를 구별하지 않습니다.
"mainMenuStyle"은 곧 "mainmenustyle"과 동일합니다.
버튼
이제 우리는 좀 더 흥미로운 버튼을 만들기 위해서 LerpzTutorialSkin 객체 속 GUI 버튼의 속성을 수정해야합니다.
우리는 같은 GUI 스킨 객체를 메뉴와 헤드업 디스플레이, 또는 'HUD'에 사용하고 있으며, 특히 HUD의 경우에는 오직 기본 폰트만 수정하면 되었습니다. 그러나 시작 메뉴에 쓰일 버튼 같은 경우는, 버튼 텍스트 뒤에 삽입될 그래픽 이미지도 필요합니다. 기본 버튼 디자인은 게임의 시각적 스타일과 맞지 않기 때문에, 변경이 필요합니다.
★ 팁
GUI 요소가 Hover(마우스가 올라올 때), Focus(포커스가 갔을 때) 그리고 Active(클릭하였을 때) 이벤트에 반응하게 하려면, 이미지가 없더라도 배경 이미지를 설정해야합니다.
Project Pane의 LerpzTutorialSkin 에셋을 클릭하여 Inspector Pane에 세부정보를 불러온 후 설정을 아래와 같이 변경합니다. (다른 GUI요소 종류는 무시하십시오; 우리는 그것들을 사용하지 않을 것입니다.)
LerpzTutorialSkin속 GUISkin 객체의 버튼 이미지 설정하기.
이제 "Play" 버튼을 추가해 봅시다:
==============================================================================
if (GUI.Button( Rect( (Screen.width/2)-70, Screen.height - 160, 140, 70), "Play"))
{
isLoading = true;
Application.LoadLevel("TheGame"); // 게임 레벨을 불러옵니다.
}
==============================================================================
위의 코드는 "Play" 버튼을 렌더링하고 이를 다루기 위한 코드입니다. 렌더링과 이벤트 핸들링을 위한 코드는 같은 곳에서 발생하게 하여 더욱 관리하기 쉽도록 하였습니다. GUI.Button()함수는 Rect 객체를 가지고 버튼의 위치와 크기, 그리고 텍스트 라벨을 정의합니다.
유저가 이 버튼을 클릭하여 참이라는 값이 돌아오면, 우리는 게임을 불러올 수 있게 됩니다.
우리는 코드에서 isLoading을 설정하여 "Loading..." 텍스트를 보여주고 유니티에게 게임 레벨을 불러 오도록 합니다.
★ 팁
새 GUI 시스템은 요소들을 그리는 여러 가지 대체 함수들을 지원하여 텍스트 대신 특정 이미지, 또는 심지어 이미지와 라벨, 툴팁이 모두 통합된 객체를 명시하도록 해줍니다. 자세한 사항은 매뉴얼을 참고 하십시오.
"Quit "버튼도 비슷하게 다루어지지만, 게임이 독립적인 빌드(또는 유니티 에디터)에서 실행되는 지 테스트하는 기능이 추가됩니다.
==============================================================================
var isWebPlayer = (Application.platform == RuntimePlatform.OSXWebPlayer || Application.platform == RuntimePlatform.WindowsWebPlayer);
if (!isWebPlayer)
{
if (GUI.Button( Rect( (Screen.width/2)-70, Screen.height - 80, 140, 70), "Quit"))
Application.Quit();
}
==============================================================================
위의 코드에서 볼 수 있듯이 이 코드는 "Play"버튼과 매우 비슷합니다. 우리는 이 버튼을 약간 아래에 그려내고, 그 이전에 버튼이 그려질 필요가 있는지 체크합니다.
마지막 단계는 사용자가 "Play"버튼을 선택하면 표시되어야하는 "Loading..." 텍스트입니다. 이 텍스트가 필요한 이유는 우리의 게임 무대가 불러와지는 데에 약간의 시간이 걸릴 수 있기 때문입니다 -- 특히 게임이 인터넷상에서 웹플레이어를 통해서 스트리밍 되는 중인 경우엔 더욱 그렇습니다.
이곳이 바로 isLoading이 활약하는 곳입니다:
==============================================================================
if (isLoading)
GUI.Label ( Rect( (Screen.width/2)-110, (Screen.height / 2) - 60, 400, 70), "Loading...", "mainMenuTitle");
}
==============================================================================
여기서 다시 한 번 우리는 mainMenuTitle 사용자 GUI 스타일을 이용하여 텍스트 스타일이 타이틀의 스타일과 매치되도록 합니다. (GUI 스타일들은 대소문자를 가리지 않기 때문에, 이름상의 대문자는 순전히 읽기 쉽게 하기위해 표기되었습니다.)
-------------------------------------------------
Quit 버튼
"Quit"버튼은 오직 게임을 독립형 어플리케이션으로 실행될 때만 작동합니다. 만약 게임이 웹플레이어, Mac의 대시보드 위젯 또는 유니티 에디터 내에서 실행될 경우에는 "Quit"버튼은 아무것도 하지 않을 것입니다. 유니티 웹플레이어는 웹페이지 자체에 내장되어 있기 때문에 종료(Quit)될 수 없거니와, 브라우저를 자동으로 닫게 하는 것도 좋은 생각이 아닙니다. (어떤 측면에서는 웹플레이어가 실행중인 페이지를 닫는 것이 하나 의 옵션일수 있다 할 수 있겠지만 이 부분은 전적으로 웹페이지 자체에서 다루는 것이 상책입니다.) 마찬가지로 대시보드 위젯에서 "Quit"옵션이 무엇을 할 수 있습니까? 위젯을 닫으면 게임은 대시보드에서 삭제될 것입니다.
그러므로 우리는 게임이 독립형 어플리케이션으로 실행되지 않을 경우 Quit버튼을 표시하지 않고 또 사용하지 않을 필요가 있습니다. 다만 예외는 게임이 유니티 에디터에서 실행되고 있을 때입니다. 왜냐하면 우리는 버튼이 제대로 표시되고 있는지, 또 잘 작동하는지 알고 싶지만 버튼이 표시되지 않으면 이를 하기 어렵기 때문입니다.
-------------------------------------------------
다음 단계는 약간의 음악을 추가하는 것입니다.
ㅁ Project Pane으로 가서 Sounds 폴더를 열고 StartMenu 오디오 파일을 Hierarchy Pane의 Main Camera 객체에 드래그 하십시오. 이리함으로서 오디오 클립 구성요소(Audio Clip Component)를 추가할 것입니다.
ㅁ Main Camera 객체를 클릭하고, Inspector창에서 새로 추가된 오디오 클립 구성요소를 찾으십시오. Play On Awake 와 Loop 체크박스에 체크하십시오.
ㅁ Main Camera 객체에 StartMenuGUI 스크립트를 추가하십시오.
ㅁ 마지막으로, StartMenuGUI 구성요소안에 GSkin의 값을 LerpzTutorialSkin으로, Backdrop의 값을 StartSplashScreen으로 설정하십시오.
이제 무대를 플레이하면, 짧고 반복된 오케스트라 음악과 함께 아래와 같은 화면을 게임 뷰에서 보게 될 것 입니다:
시작 메뉴가 실행되고 있습니다.
이게 끝입니다! 우리의 시작 메뉴는 완성되었습니다.
★ 팁
게임에 사용된 음악은 애플사의 Orchestral Jam Pack의 Apple Loops를 채택, GarageBand를 이용하여 어레인지 하였습니다. 이는 Mac 사용자들이 플레이스홀더 음원(placeholder tune)을 만드는 데에 매우 유용한 도구입니다. 이 도구들을 이용하여 어떠한 음악적 스타일이 게임에 제일 맞는지 결정할 수 있습니다. PC 사용자에게는 Audacity를 사용하기를 권장합니다.
사용자 고유의 프로젝트에는 옵션 메뉴를 추가하고 싶을 수도 있으며, 어쩌면 고득점 메뉴 또는 멀티플레이어 로비, 등을 추가할 수도 있습니다. 이 모든 것들이 Unity 2 GUI를 사용하여 만들어질 수 있습니다.
게임 오버
게임 오버 화면은 플레이어가 게임을 끝마쳤거나 도전에 실패했을 때 표시됩니다. 시작 메뉴와는 달리 이 씬은 버튼이나 다른 시각적인 사용자와의 상호작용이 없습니다: 그저 짧은 음악이 재생되는 동안 배경위에 "Game Over"메시지를 띄웁니다. 음악의 재생이 끝나거나 사용자가 마우스를 클릭하면, 자동으로 "Start Menu" 씬을 불러옵니다.
ㅁ 먼저, 새로운 무대를 만들고 "GameOver"라고 이름 짓습니다.
ㅁ GameOverJingle 오디오 파일을 기본 Main Camera 객체에 드래그 해놓고 아래와 같이 설정합니다:
GameOverJingle의 설정
우리는 편집기를 이용하여 씬에 다른 것을 더 추가할 필요가 없습니다: 기본 카메라 혼자면 충분합니다.
다음 단계는 스크립트를 짜는 것입니다(부록에서 완성된 스크립트를 찾을 수 있습니다):
ㅁ 새 Javascript 자산을 만들고 "GameOverGUI"라고 이름 짓습니다.
ㅁ 편집기를 이용해 스크립트를 열고 아래 설명된 코드를 추가합니다:
시작 메뉴와 마찬가지로, 우리는 프로젝트가 실행되지 않을 때에도 유니티 에디터에서 GUI를 볼 수 있기를 바라기 때문에 아래의 코드를 추가하십시오:
==============================================================================
@script ExecuteInEditMode()
==============================================================================
시작 메뉴에는 LerpzTutorialSkin GUI스킨 자산을 사용하였습니다. GUI 스킨은 수많은 GUI 스타일을 정의하며 다수의 GUI에 적용할 수 있도록 해줍니다.
다른 대체적인 테크닉으로는 개개인의 GUI 스타일 객체를 직접 정의하는 것입니다. 우리는 이 방법을 사용하여 Game Over 스크립트에 Inspector창에서 차후 설정할 수 있는 3개의 GUIStyle 변수와 텍스트 요소를 정의하고 크기를 변경하는 2개의 변수를 정의할것입니다:
==============================================================================
var background : GUIStyle;
var gameOverText : GUIStyle;
var gameOverShadow : GUIStyle;
==============================================================================
우리는 곧 이 GUI 스타일 객체들을 Inspector 창에서 설정할 것입니다.
다음은 "Game Over"메시지의 텍스트 계수인자를 설정해야합니다. 이는 "Game Over"메시지가 기본 폰트 크기보다 크게 렌더링될 것이기 때문입니다.
우리는 이 메시지를 두가지의 다른 색깔로 두번 그려내어, 그림자가 드리워진것 같은 효과를 줄것이기 때문에, 2개의 크기 변수를 정의합니다.
==============================================================================
var gameOverScale = 1.5;
var gameOverShadowScale = 1.5;
==============================================================================
드디어 우리는 OnGUI()함수에 착수할 수 있습니다:
==============================================================================
function OnGUI()
{
==============================================================================
먼저 배경막을 시작 메뉴에 사용되었던 것처럼 크기를 재조정합니다:
==============================================================================
GUI.Label ( Rect( (Screen.width - (Screen.height * 2)) * 0.75, 0, Screen.height * 2, Screen.height), "", background);
==============================================================================
다음은 "Game Over" 메시지의 그림자가 드리워진 버전을 그리는 것입니다. 우리는 텍스트의 크기를 키우고 화면 중앙에 렌더링 해야 합니다. 다행히도, 우리는 GUI시스템에 내장된 변형 매트릭스를 사용하여 크기조정을 다루도록 할 수 있습니다.
★ 팁
GUI 변형 매트릭스는 또한 그 어떤 임의적인 변형을 수행하는데 사용될 수 있습니다: 마음대로 크기조정, 회전, 뒤집기 그리고 선회 등을 할 수 있습니다.
텍스트가 어두운, 그림자 색깔로 표시되는 것을 확인하기 위해서 gameOverShadow GUI 스타일을 GUI.Label() 함수로 보냅니다.
==============================================================================
GUI.matrix = Matrix4x4.TRS(Vector3(0, 0, 0), Quaternion.identity, Vector3.one * gameOverShadowScale);
GUI.Label ( Rect( (Screen.width / (2 * gameOverShadowScale)) - 150, (Screen.height / (2 * gameOverShadowScale)) - 40, 300, 100), "Game Over", gameOverShadow);
==============================================================================
마지막으로, 우리는 똑같은 텍스트를 또 그리지만 약간 밝은 색깔로 그립니다. 유니티의 GUI 시스템은 언제나 이 요소들을 코드에 나타나는 순서대로 렌더링하기 때문에, 이 텍스트는 그림자 위에 나타날 것입니다. gameOverScale 계수인자와 gameOverText GUI 스타일을 제외하고는 추가로 다른 점은 없습니다.
==============================================================================
GUI.matrix = Matrix4x4.TRS(Vector3(0, 0, 0), Quaternion.identity, Vector3.one * gameOverScale);
GUI.Label ( Rect( (Screen.width / (2 * gameOverScale)) - 150, (Screen.height / (2 * gameOverScale)) - 40, 300, 100), "Game Over", gameOverText);
}
==============================================================================
ㅁ 스크립트를 저장하고 Main Camera에 드래그 해놓습니다.
ㅁ Main Camera 객체를 클릭하여 Inspector 창을 불러옵니다. 이제 변수들을 설정할 시간입니다...
ㅁ 먼저, 배경의 GUI 스타일을 다룹니다. 이는 간단히 "GameOverSplashScreen" 이미지를 아래와 같이 Normal->Background 슬롯에 드래그 해놓으면 됩니다:
적절한 배경 GUI 스타일의 설정의 좋은 예.
ㅁ 다음 우리는 게임 오버 텍스트 GUI 스타일을 아래의 그림과 같이 설정할 것입니다. (평소와 같이, 다른 설정들은 그대로 놔두십시오.)
적절한 게임 오버 텍스트 GUI 스타일의 설정.
ㅁ 다음 Game Over Scale의 값을 1.69로 설정합니다.
ㅁ 이제 게임 오버 그림자 GUI 설정에는:
적절한 게임 오버 그림자 GUI 스타일의 설정.
ㅁ 마지막으로 Game Over Shadow Scale의 값을 1.61로 설정합니다.
이제 아래와 같이 게임 뷰에 나타나는 GUI를 볼 수 있을 것입니다:
게임 오버 화면.
마무리해야 할 사항은 두 번째 스크립트를 Main Camera에 추가하는 것입니다. 이 스크립트는 음악의 재생이 끝났는지 체크하며 만약 끝났다면 시작 메뉴 무대를 불러오는 기능을 합니다.
ㅁ 새 Javascript 자산을 만듭니다. GameOverscript라고 이름 짓습니다.
ㅁ 스크립트를 열고 아래의 코드를 추가하십시오. (완전한 코드는 부록에서 찾아볼 수 있습니다.)
==============================================================================
function LateUpdate ()
{
if (!audio.isPlaying || Input.anyKeyDown)
Application.LoadLevel("StartMenu");
}
==============================================================================
이 코드는 오디오가 재생을 끝냈는지 또는 플레이어가 시작 메뉴를 불러오기 전에 키를 눌렀는가를 체크합니다
GameOverscript를 Main Camera에 추가하면 끝입니다: GUI가 완료 되었습니다!
본 튜토리얼 번역서는 (주)지피엠스튜디오가 운영하는 "유니티코리아" 회원님들을 위한 메뉴얼 번역 자료 입니다.
본 자료를 다른 곳에 개제 하실 때에는 아래의 번역과 출처를 명확히 밝혀 주시기 바랍니다.
본 자료는 제3자가 상업적인 용도로 사용 할 수 없음을 밝힙니다.
번역 : 유니티코리아 [U3K]게임인생
출처 : 유니티코리아(www.unity3dkorea.com)
GUI도 2편으로 끝이 났습니다. 다음 회차에는 Adversareis (적)을 만드는 튜토리얼을 연재 하겠습니다.