스크립트 기본 준비
기본적으로 GUI를 사용하기 위해서는 2가지 사전 준비가 필요하다.
1. 스크립트에 UnityEditor를 사용함을 명시한다.
2. 해당 클래스의 부모를 EditWindow로 지정한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor; // UnityEditor 사용
public class TestEditorWindow : EditorWindow // EditorWindow를 부모로 지정
{
}
유니티 Scene에 새로운 스크립트 TestEditorWindow를 만들어
위와 같이 수정한다.
새로운 윈도우 만들기
GUI를 만드려면 그 GUI를 그리기 위한 도화지(윈도우)가 필요하다.
여기서 상속했던 EditorWindow의 함수를 사용한다.
var window = GetWindow<class>();
해당 class 데이터 타입의 윈도우를 생성한다.
window.title = "이름";
윈도우의 타이틀을 "이름"으로 바꾼다.
여기서 사용한 var이라는 키워드는 컴
파일러가 자동적으로 알맞은 데이터 타입으로 바꿔 변환해 주는 것이다.
즉, var가 자동적으로 GetWindow <class>의
class 데이터 타입으로 변한다는 것이다.
아주 편리하다고 할 수 있다.
이제 UnityEditor에 있는 [MenuItem]을
유니티 Scene에 새로운 옵션 창을 추가할 것이다.
[MenuItem("옵션 경로 및 이름")]
static void function()...
("옵션 경로 및 이름")으로 된 옵션을 Scene에 새로 생성한다.
그 창을 클릭하면 밑에 있는 function()을 실행한다.
여기서 "옵션 경로 및 이름"이라고 했는데
이는 [MenuItem("a/b")]라고 했다면 a 안에 b가 있다는 뜻으로
폴더를 구분하듯이 좀 더 선택지를 늘려나갈 수 있음을 뜻한다.
그리고 여기서 실행하는 함수는
항상 정적(static)으로 선언해야 한다는 특징이 있다.
이제 위에서 설명한 두 개를 이용해서 새로운 창을 만들어보자.
public class TestEditorWindow : EditorWindow
{
[MenuItem("MyTool/OpenTool %g")]
static void Open() // 새로운 창을 만드는 Open() 함수
{
var window = GetWindow<TestEditorWindow>();
window.title = "myTool"; // 창 이름을 myTool로 지정
}
}
여기서 % g는 단축키를 지정해 주는 것인데,
Ctrl + g를 누르면 바로 해당 옵션이 실행되도록 하는 것이다.
이제 Scene으로 돌아가보자.
상단에 MyTool이라는 옵션이 생겼고 그 안에 OpenTool이 생겼다.
그리고 OpenTool을 누르면 myTool이라는
타이틀을 가진 새로운 윈도우 창이 나오는 것을 확인할 수 있다.
GUI 그리기
4가지 GUI 그리는 방식
GUI를 그리는 방식은 총 4가지가 있다.
GUI.Label(new Rect(..), "텍스트");
GUILayout.Label("텍스트");
EditorGUI.LabelField(new Rect(..), "텍스트");
EditorLayout.LableField("텍스트");
모두 동일하게 "텍스트" 이름을 가진 라벨을 만드는 GUI 함수들이다.
총 두 가지 기준으로 분류할 수 있을 것이다.
1. Layout의 유무
Layout이 붙은 것과 붙지 않은 것의 차이를 알아보기 위해 이렇게 코드를 작성한다.
//GUI 함수를 호출할 때 어디에서 호출하는지도 중요함
//ex : onGUI() 안에 있는 코드들을 Update()에서 출력하면 에러
private void OnGUI()
{
GUI.Label(new Rect(50, 50, 100, 50), "GUILabel");
GUI.Label(new Rect(60, 50, 50, 50), "GUILabel");
}
기본적으로 GUI를 그려주기 위해선 OnGUI 함수 위에 그려줘야 한다.
만약 Update나 다른 곳에 GUI 함수를 사용한다면 에러가 뜨니 조심하자.
GUI 함수는 어디에서 호출하는지도 중요하다.
여기서 Rect는 Label의 위치와 크기를 뜻한다.
이렇게 임의로 Rect를 지정하고 GUILabel이라는 텍스트를 2개를 만들어보면?
이렇게 글자가 서로 겹치게 된다.
이를 GUILayout으로 코드를 수정해 본다.
private void OnGUI()
{
// Layout을 따로 Rect를 지정해주지 않는다.
GUILayout.Label("GUILayout");
GUILayout.Label("GUILayout");
}
아무런 설정이 없었음에도,
2개의 Label Text가 겹치지 않고 나란히 나오는 것을 확인할 수 있다.
이는 EditorGUI와 EditorGUILayout도 마찬가지이다.
정리하자면
Layout이 붙은 GUI설정은 따로 Rect를 지정해 줄 필요가 없으며,
자동적으로 보기 좋게 배치를 조정해 준다.
그렇지 않은 것은, Rect를 스스로 조정해서 배치를 해줘야 한다.
2. Editor의 유무
Editor 간의 차이를 알아보기 위해
EditorGUILayout과 GUILayout 이 2개를 사용한다.
private void OnGUI()
{
GUILayout.Label("GUILayout");
EditorGUILayout.LabelField("EditorGUILayout");
EditorGUILayout.LabelField("EditorGUILayout");
GUILayout.Label("GUILayout");
GUILayout.Label("GUILayout");
EditorGUILayout.LabelField("EditorGUILayout");
GUILayout.Label("GUILayout");
}
이런 식으로 GUILayout과 EditorGUILayout을 반복호출 하였다.
myTool을 확인해 보면 두 GUI의 차이는 없어 보인다.
정말 차이가 없을까?
두 개의 차이는 아래와 같다.
GUI / GUILayout -
런타임 / Editor 사용 가능
EditorGUI / EditorGUILayout -
Editor에서만 사용 가능(런타임 사용 x)
이게 무슨 말이며 또 왜 중요할까?
중요한 이유는 즉 GUI가 Scene에서 필요한 경우가 생기기 때문이다.
즉, 해당 스크립트를 게임오브젝트에 넣어야 할 상황이 생기기 때문이다.
그런 상황을 가정해 보자.
새로운 스크립트 TestCode.cs를 만들어 이렇게 만든다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestCode : MonoBehaviour
{
private void OnGUI()
{
GUILayout.Label("GUILayout");
EditorGUILayout.LabelField("EditorGUILayout"); // 오류
}
}
전과 다르게 TestCode는 여전히 MonoBehaviour을 상속받는다.
이를 EditorWindow로 상속을 바꾸면
게임오브젝트의 컴포넌트로 사용할 수 없다.
이러한 조건일 때,
GUI는 사용할 수 있지만 Editor는 사용할 수 없다.
왜냐하면 Editor는 정말 에디터 상에서만 사용 가능하도록 설계됐기 때문이다.
이렇게 GameObject에 Test Code 스크립트를 넣고 실행해 보면
게임화면에 만들어진 GUI가 뜨는 것을 확인할 수 있다.