본문 바로가기

Unity

유니티 - 커스텀 에디터 (Custom Editor)

반응형

 

커스텀 에디터 기능을 이용한 ScriptableObject 생성을 조금 더 편하게 도와줄 에디터를 만들어 볼까 합니다.

 

유튜브 AdamCyounis를 보다 편할 것 같아 만들어 보았습니다.

https://www.youtube.com/channel/UC08QfQDLAd9D7aYPFgBUIng

 

AdamCYounis

Catch me live on twitch: Mon, Tues, Wednesday and Fri 1-6pm AEST. Twitch: http://twitch.tv/adamcyounis Twitter: http://twitter.com/adamcyounis Discord: https://discord.gg/9WkRG7s Become a Patron at https://www.patreon.com/adamcyounis Check out my game Insi

www.youtube.com

 

전체 소스

using UnityEngine;
using UnityEditor;
using System;

#if UNITY_EDITOR
public class TestScriptableObject : EditorWindow {
    Vector2 scrollPosition;

    [MenuItem("CustomUI/ScriptableObject")]
    static void Init() {
        var window = (TestScriptableObject) EditorWindow.GetWindow(typeof(TestScriptableObject));
        window.Show();
    }

    private void OnGUI() {
        scrollPosition = GUILayout.BeginScrollView(
            scrollPosition, GUILayout.MinWidth(100), GUILayout.MaxWidth(300), GUILayout.MinHeight(220), GUILayout.MaxHeight(700));

        if (GUILayout.Button("ScriptableObject 1")) {
            if (!FileCheck("NewDefenseWeapon")) {
                CreateScriptableObject<DefenseWeapon>("");
            }
        }
        if (GUILayout.Button("ScriptableObject 2")) {
            if (!FileCheck("NewWeaponValue")) {
                CreateScriptableObject<WeaponValue>("/WeaponValue");
            }
        }
 
        GUILayout.EndScrollView();
    }

    bool FileCheck(string fileName) {
        string[] a = AssetDatabase.FindAssets(fileName);

        if (a.Length > 0) {
            Debug.Log($"{fileName}과 같은 이름의 파일이 존재합니다. 파일명을 수정하세요");
            return true;
        } 
        return false;
    }
    
    private void CreateScriptableObject<T>(string path) where T : ScriptableObject {
        var value = ScriptableObject.CreateInstance<T>();
        AssetDatabase.CreateAsset(value, "Assets/ScriptableObject" + path + "/New" + typeof(T).ToString() + ".asset");
        AssetDatabase.SaveAssets();
        
        EditorUtility.FocusProjectWindow();
        Selection.activeObject = value;
    }
}
#endif

 

 

(준비물) 본인의 ScriptableObject가 있을 겁니다 (예로 아래 소스처럼)

using UnityEngine;

[CreateAssetMenu(menuName = "ScriptableObject/DefenseWeapon")]
public class DefenseWeapon : ScriptableObject {
    public string towerID;
    public string towerName;
    public Sprite towerImage;
}

 

Vector2 scrollPosition;

[MenuItem("CustomUI/ScriptableObject")]
static void Init() {
   var window = (TestScriptableObject) EditorWindow.GetWindow(typeof(TestScriptableObject));
   window.Show();
}

(TestScriptableObject) EditorWindow.GetWindow(typeof(TestScriptableObject))

=> TestScriptableObject C# 파일명을 넣으시면 됩니다.

유니티 상단 메뉴 목록에 새로운 메뉴를 추가합니다.(아래 이미지 참조)

 

scrollPosition = GUILayout.BeginScrollView(
            scrollPosition, GUILayout.MinWidth(100), GUILayout.MaxWidth(300), GUILayout.MinHeight(220), GUILayout.MaxHeight(700));

위쪽 메뉴창을 화면에 표시했을 때 목록이 많아지면 스크롤바를 표시해 줍니다.(아래 이미지 참조)

 

if (GUILayout.Button("ScriptableObject 1")) {
   if (!FileCheck("NewDefenseWeapon")) {
       CreateScriptableObject<DefenseWeapon>("");
   }
}

버튼 하나를 만들어 줍니다. (위쪽 참고 이미지처럼 버튼 하나의 역할을 합니다.)

FileCheck => 생성될 ScriptableObject의 같은 파일명이 있나 검사를 합니다.

% 파일명 검사는 New + ScriptableObject명으로 하시면 됩니다. 아래 ScriptableObject 생성 소스 참조 %

 

CreateScriptableObject<DefenseWeapon>(""); => "DefenseWeapon" 대신 본인의 ScriptableObject의 이름으로..

("") => 생성될 파일의 폴더명을 입력해 주시면 됩니다. 폴더명이 있다면 폴더명 앞에 "/"를 꼭 넣어 주세요.

% 생성될 파일이 위치할 폴더는 미리 생성 해 주셔야 합니다 %

 

bool FileCheck(string fileName) {
   string[] a = AssetDatabase.FindAssets(fileName);

   if (a.Length > 0) {
       Debug.Log($"{fileName}과 같은 이름의 파일이 존재합니다. 파일명을 수정하세요");
       return true;
   } 
   return false;
}

파일 생성시 같은 이름이 있나 체크를 합니다.

% 같은 이름의 파일을 연속 생성하려고 하면 오류가 생기더군요. %

 

private void CreateScriptableObject<T>(string path) where T : ScriptableObject {
   var value = ScriptableObject.CreateInstance<T>();
   ssetDatabase.CreateAsset(value, "Assets/ScriptableObject" + path + "/New" + typeof(T).ToString() + ".asset");
   AssetDatabase.SaveAssets();
        
   EditorUtility.FocusProjectWindow();
   Selection.activeObject = value;
}

파일을 생성 시켜 줍니다.

CreateScriptableObject<T>(string path) => 생성될 ScriptableObject를 받기 위해 제네릭으로 처리.

string path => 저장될 마지막 폴더명을 받아 옵니다.

AsserDataBase.SaveAssets() => 지정된 ScriptableObject를 생성시켜 줍니다.

EditorUtility.FocusProjectWindow(); => 파일 생성 후 화면의 포커스를  Project 창으로 이동시켜 주며

Selection.activeObject = value; => 생성된 파일을 선택합니다.

 

 

생성 버튼을 클릭하면 Project창의 사용자가 지정한 위치에 ScriptableObject 파일이 생성됩니다.

 

간단한 기능이지만 본인의 게임 프로젝트 안의 ScriptableObject의 목록을 별도로 관리할 수 있어 조금은 편리하지 않을까 합니다.

% 프로젝트에 적용하기 전 필히 프로젝트 파일을 복사하신 후 테스트하시기 바랍니다 %

반응형