제8장 MenuItem

2019. 8. 13. 23:40유니티/(Old)에디터 확장

 

Unity エディター拡張入門

Web版無償公開中!Unityエディター拡張の入門書!

anchan828.github.io

에디터 확장에서 MenuItem을 모르면 아무것도 할 수 없을 정도로 중요한 MenuItem에 대해서 설명하는 장 입니다. 이 장에서는 MenuItem으로 할 수 있는 것을 소개하고자 합니다. 사용하기 위해서 어떤 방법으로 접근해야 되는지 가볍게 설명하지만 이 장 이외에 너무 많이 사용되므로 자연스럽게 이해가 됩니다.

8.1 MenuItem이란

MenuItem은 Unity 에디터 상단에 있는 메뉴 바와 컨텍스트 메뉴의 항목을 추가하기 위한 기능입니다.

그림 8.1 : [독자적으로 추가한 항목(独自に追加した項目)]이란 부분을 추가한 메뉴의 항목입니다.
그림 8.2: [스크립트에 추가한 항목(スクリブトに追加した項目)]이란 부분을 추가한 컨텍스트 메뉴의 항목입니다.

8.2 MenuItem의 용도

메뉴는 특정 트리거에 의해서 사용됩니다. 유니티 표준에서는

  • GameObject를 생성 ( GameObject/Create Empty )
  • 씬 작성 ( File/New Scene )
  • 윈도우의 표시 ( Window/Inspector )

와 같은 경우 메뉴를 사용합니다.

 

사용자가 MenuItem을 사용해서 독자적인 메뉴를 추가하려면 임의의 타이밍으로 Editor 스크립트를 실행해야합니다. 이에 대한 목적을 대략적으로 살펴보면

  • 독자적인 윈도우를 표시
  • AssetBundle의 작성
  • Asset을 작성
  • 선택한 Asset에 대한 특정 액션을 실행

등이 있습니다. 이러한 것들을 실행하기 위한 트리거가 바로 MenuItem입니다.

8.3 MenuItem을 사용하여 메뉴를 표시하기

먼저 간단하게 메뉴를 추가해보겠습니다. MenuItem은 Attribute로써 제공되며 static 함수에 부가하는 것으로 동작합니다.

using UnityEditor;
 
public class NewBehaviourScript
{
    [MenuItem("CustomMenu/Example")]
    static void Example ()
    {
    }
}

그림 8.3 : CustomMenu의 메뉴 항목과 Example의 하위 항목을 추가

물론 기존의 메뉴에 하위 항목을 추가하는 것도 가능합니다.

using UnityEditor;
 
public class NewBehaviourScript
{
    [MenuItem("Assets/Example")]
    static void Example ()
    {
    }
}

그림 8.4 : Asset 메뉴에 Example 메뉴를 추가

하위의 메뉴에 또 다른 하위 항목을 작성하는 것도 가능합니다.

using UnityEditor;
 
public class NewBehaviourScript
{
    [MenuItem("CustomMenu/Example/Child1/Grandchild")]
    static void Example1 ()
    {
    }
 
    [MenuItem("CustomMenu/Example/Child2/Grandchild")]
    static void Example2 ()
    {
    }
}

그림 8.5 : 하위을 생성하는 깊이의 제한은 특별히 없지만 조작성을 생각하면 3개까지만 추천하는 바 입니다.

8.4 실행할 수 없는 MenuItem을 작성하기

MenuItem으로 추가한 메뉴를 상황에 따라서 실행되지 말아야되는 경우가 있습니다. 그렇기에 MenuItem으로 추가한 메뉴를 실행되지 않게 하는 기능이 있습니다.

그림 8.6 : Child2 메뉴의 문자가 회색으로 되어 있으며, 실행할 수 없습니다.

MenuItem의 두 번쨰 인수인 isValidateFunction가 존재하는데, 이 인수는 메뉴를 표시할 때 실행 가능을 설정할 수 있습니다. isValidateFunction가 true면 트리거에 해당되는 함수는 bool형을 리턴하는 Validate 함수로써 취급되며 이 함수의 리턴 값을 true로 넘겨주면 실행 가능, false로 설정하면 실행 불가로 됩니다.

 

추가적으로 Validate 함수는 단독으로 사용할 수 없습니다. 반드시 isValidateFunction가 true로 설정되어야 있어야 동작합니다. isValidateFunction는 기본적으로 false로 설정되어 있기 때문에 생략이 가능합니다.

(P.S 원본 사이트에서는 isValidateFunction가 false로 설정되어 있어야 동작한다고 나와있지만 실제로 테스트 해본 결과 false일 경우 제대로 동작하지 않습니다. 오타인 듯)

using UnityEditor;
 
public class NewBehaviourScript
{
    [MenuItem("CustomMenu/Example/Child1")]
    static void Example1 ()
    {
    }
 
    //isValidateFunction가 false
    [MenuItem("CustomMenu/Example/Child2")]
    static void Example2 ()
    {
    }
 
    //isValidateFunction가 true
    [MenuItem("CustomMenu/Example/Child2"true)]
    static bool ValidateExample2 ()
    {
        //false로 리턴하면 실행 불가
        return false;
    }
}

8.5 MenuItem의 표시 순서를 변경하기

메뉴의 표시 순서를 설정하는 것이 가능합니다. MenuItem의 세 번째 인수인 priority로 지정합니다.

그림 8.7 : Example 메뉴가 가장 밑에서 가장 위로 이동

using UnityEditor;
 
public class NewBehaviourScript
{
    [MenuItem("Assets/Example"false1)]
    static void Example ()
    {
    }
}

priority의 사양

priority의 수치를 작게 설정할 수록 상위에 표시됩니다.

그림 8.8 : priority가 왼쪽으로부터 1, 20, 40, 1000으로 설정했을 때

또한 priority의 값을 이전의 최댓값에서 11 차이를 둘 경우 항목간의 세퍼릿(구분선)을 지을 수 있습니다.(자세한 것은 코드를 참고해주세요.)

그림 8.9 : Example2와 Example3의 사이에 구분선

using UnityEditor;
 
public class NewBehaviourScript
{
    [MenuItem("CustomMenu/Example1"false1)]
    static void Example1 ()
    {
    }
 
    [MenuItem("CustomMenu/Example2"false2)]
    static void Example2 ()
    {
    }
 
    //Example2와 Example3의 차이는 11(13 - 2)이므로 구분선이 생깁니다.
    [MenuItem("CustomMenu/Example3"false13)]
    static void Example3 ()
    {
    }
}

8.6 MenuItem에 체크 마크 넣기

Menu.GetChecked 와 Menu.SetChecked를 사용하는 것으로 하위 메뉴에 체크 마크를 넣는 것이 가능합니다.

그림 8.10 : 체크 마크를 넣는 것으로 현재 무엇가를 사용하고 있다는 것을 알 수 있습니다.

using UnityEditor;
 
public class NewBehaviourScript
{
    [MenuItem("CustomMenu/Example")]
    static void Example ()
    {
        var menuPath = "CustomMenu/Example";
        var @checked = Menu.GetChecked (menuPath);
        Menu.SetChecked (menuPath, !@checked);
    }
}

8.7 핫 키(단축키) 설정하기

MenuItem으로 추가한 메뉴에 핫 키를 설정할 수 있습니다. MenuItem의 첫 번쨰 인수의 마지막에 문자열을 조합하여 핫 키를 설정할 수 있습니다.

using UnityEditor;
using UnityEngine;
 
public class NewBehaviourScript
{
    //command(ctrl) + shift + g
    [MenuItem("CustomMenu/Example %#g")]
    static void Example ()
    {
        Debug.Log ("실행");
    }
}

표 8.1 : 단축키 조합에 관련된 표

특수 문자 의미
% Ctrl(Windows)または command(MacOSX)
# Shift
& Alt(Windows)または option(Mac OS X)
_ 修飾子キー無し
F1 ... F12 ファンクションキー
HOME Home キー
END End キー
PGUP PageUp キー
PGDN PageDown キー
KP0 ... KP9 0から9までの数字キー
KP. .
KP+ +
KP- -
KP* *
KP/ /
KP= =

기능키(펑션키, F1, F2... 등)만의 단축키는 작성할 수 없습니다.

8.8 CONTEXT

각 컴포넌트의 톱니바퀴 모양을 클릭하면 표시되는 컨텍스트 메뉴에 항목을 추가할 수 있습니다.

그림 8.11 : 톱니바퀴 모양을 클릭하면 표시되는 컨텍스트 메뉴

Context 메뉴에 항목을 표시하려면 규칙이 있습니다. 메뉴 항목에서 첫 번쨰 인자에서 경로를 지정할 때 서두는 반드시 "CONTEXT/"로 시작해야하며, 그 다음은 "CONTEXT/컴포넌트 명/항목 이름"으로 지정해야합니다.

using UnityEditor;
 
public class NewBehaviourScript
{
    //Transform에 메뉴를 추가
    [MenuItem("CONTEXT/Transform/Example1")]
    static void Example1 () { }
 
    //모든 컴포넌트에 메뉴를 추가
    [MenuItem("CONTEXT/Component/Example2")]
    static void Example2 () { }
 
    //ExampleScript(스크립트)에 메뉴를 추가
    [MenuItem("CONTEXT/ExampleScript/Example3")]
    static void Example3 () { }
}

컨텍스트 메뉴에 대응하는 핫 키는 사용할 수 없습니다. 컴포넌트에 해당되는 컨텍스트 메뉴이므로 컴포넌트 별로 단축키를 생성할 수가 없습니다.

 

MenuCommand

컨텍스트 메뉴에서만 MenuCommand를 인수로 받아서 컴포넌트의 정보를 얻을 수 있습니다.

using UnityEditor;
using UnityEngine;
 
public class NewBehaviourScript
{
    [MenuItem("CONTEXT/Transform/Example1")]
    static void Example1 (MenuCommand menuCommand)
    {
        //실행한 Transform의 정보를 얻을 수 있습니다.
        Debug.Log (menuCommand.context);
    }
}

그림 8.12 : 위의 코드를 Main Camera의 Transform로 실행한 결과

 

 

 

 

 

'유니티 > (Old)에디터 확장' 카테고리의 다른 글

제9장 CustomEditor  (1) 2019.08.14
제7장 EditorWindow  (0) 2019.08.11
제 6장 EditorGUI (EditorGUILayout)  (0) 2019.07.28
제 5장 SerializedObject에 대해서  (0) 2019.07.28
제4장 ScriptableObject  (0) 2019.07.28