개요
해당 방법을 통해 Unity 에서, 사용자 정의 메뉴를 추가하고, 데이터를 관리할 수 있는 인터페이스를 생성할 수 있음.
구성은 크게,
- 메뉴를 추가,
- 메뉴 선택 시, 띄울 화면 구성
- 메뉴에서 관리할 데이터의 관리 (저장하기, 불러오기)
로 구성된다.
메뉴 구성 방법
메뉴는 Static Function 에 MenuItem Attribute 를 통해 구성 가능하다.
-
Static Method를 생성함
public static void MyMenu() { … }
-
Menu Item Annotation을 통해 해당 메뉴를 구성한다.
[MenuItem(“MyMenu/ My Settings”)]
-
화면 표출 코드
화면을 노출 시키기 위해 아래 코드를 추가함
EditorWindow EditorWindow.GetWindow(System.Type windowType, bool utility, string title) (+ 12 overloads)
MySettingWindow window = (MySettingWindow)GetWindow(typeof(MySettingWindow), false, “My Settings”);
[전체 코드]
[MenuItem(“MyMenu/My Settings”)]
public static void MyMenu() {
MySettingWindow window = (MySettingWindow)GetWindow(typeof(MySettingWindow), false, “My Settings”);
}
화면 구성
띄워질 화면에서 구성할 요소들을 설정한다.
OnGUI() 메소드
해당 메소드는, 매 프레임 마다, 호출되는 메소드로, GUI 핸들링 기능을 제공하는 메소드
데이터 변수
데이터를 관리할 변수들을 추가한다.
private bool toggleValue;
화면에 요소를 노출하고, 변수에 대입
EditorGUILayout 메소드 들을 통해, 화면에 UI를 배치하고, 데이터를 대입한다. 해당 메소드는, 이름으로 지정된 인스턴스가 생성되어 있는지 확인하고, 생성되지 않았으면, 2번째 인자의 초기값을 통해 인스턴스를 생성하고 초기값을 그대로 리턴 한다. 만약 인스턴스가 존재하면, 해당 인스턴스의 현재 값을 리턴 한다.
toggle = EditorGUILayout.Toggle(“Enable Feature”, toggleValue);
Toggle
EditorGUILayout.Toggle(string title, bool value);
Silder
EditorGUILayout.Slider(string title, float value);
Button
버튼의 경우는, 클릭 되었을 경우 true를 리턴 하고, 그렇지 않으면, false를 리턴 한다.
if (GUILayout.Button(“Button Title”)) { … }
데이터 관리
설정된 데이터는 Unity가 재 시작 되면, 기존에 입력했던 데이터가 모두 초기화 된다. 해당 데이터는 다음과 같은 방법으로 저장 및 로드 할 수 있다.
데이터 저장
EditorPrefs.SetBool(“TITLE”, toggleValue);
EditorPrefs.SetFloat(“TITLE”, sliderValue);
데이터가 저장되는 TITLE 구분자는 유니크한 값이어야 한다. 그렇지 않아 중복될 경우, 이전 값이 덮어쓰여짐에 주의해야 함
데이터 로딩
toggleValue = EditorPrefs.GetBool(“TITLE”);
silderValue = EditorPrefs.GetFloat(“TITLE”);
구현 위치
데이터 로딩은, OnGUI() 에서, Window를 구성한 이후, 바로 호출해 주면, 화면이 구성되면서, 이전 데이터를 로딩할 수 있으며,
데이터 저장은, Apply 버튼을 구성하여 저장하는 방법(위에서 설명한 Button)이나, 아래와 같이 실시간으로 저장되도록 구성함
private void OnGUI() {
…
bool newToggleValue = EditorGUILayout.Toggle(“TITLE”, toggleValue);
if (newToggleValue != toggleValue) {
toggleValue = newToggleValue;
ApplySettings();
}
…
}
다른 클래스나 컴포넌트에서 데이터 가져오기
Singleton Pattern을 통한 데이터 공유
Singleton Pattern의 클래스를 생성하여 데이터를 입력한 후, 다른 클래스나 컴포넌트에서 데이터를 호출할 수 있는 인터페이스를 제공한다.
public class SettingsManager : MonoBehavior
{
public static SettingsManager Instance { get; set; }
// … 관리될 변수 정의
private void Awake() {
if (Instance == null) {
Instance = this;
DontDestroyOnLoad(gameObject); // 씬 간 데이터 유지
}
else {
Destroy(gameObject);
}
}
}
ScriptableObject
ScriptableObject 를 통해 데이터에 접근
아래와 같은 ScriptableObject 클래스를 생성하면, 해당 데이터는 Create Assets 메뉴를 통해 컴포넌트를 생성할 수 있고, 해당 Assets 은 단순히 Project 에 Asset 을 생성해 놓는 것 만으로도 인스턴스 화 되어 데이터에 접근할 수 있다. 또한 Assets으로 생성된 객체에 접근하여 데이터를 수정하면, 수정된 데이터가 파일로 저장되어 지속적으로 영속화 되어 프로젝트 재 시작 시에도 이전 설정된 데이터 값이 계속 유지된다.
이는 Object에 Component로 등록 되어야만 인스턴스 화 되는 MonoBehavior와는 다른 형태로 동작하며, Settings 데이터등을 관리하기에 최적화 되어 있는 클래스 타입으로 볼 수 있다.
[CreateAssetMenu(fileName = “SettingsData”, menuName = “Settings/SettingsData”, order = 1)]
public class SettingsData : ScriptableObject
{
public bool toggleValue = false;
public float sliderValue = 1.0f;
}
이 경우는 간혹 Windows 에서 변경한 데이터의 변경 사항을 감지하지 못하여 데이터가 저장되지 않는 경우가 발생한다. 이를 방지하기 위하여 GUI 에서, Changed를 감지하여 저장하는 로직을 추가함
if (GUI.changed) {
EditorUtility.SetDirty(settinsData); // 데이터 변경을 강제로 설정
AssetDatabase.SaveAssets(); // Asset Database 에 데이터 저장 명령을 직접 호출
}
Static Object
전역 데이터로 변수를 생성하여 관리하는 방식으로, 추천하지 않는다.