본문 바로가기

유니티/GUI (IMGUI) 및 Editor

[Unity] 메뉴 아이템 (MenuItem)

반응형

커스텀 에디터

에디터를 편집하려면?

유니티는 기본적으로 컴포넌트, 에셋 등을 편집하기 위한 편집기를 제공한다.

그러나 기본 기능 외에 특정 컴포넌트나 에셋에 대한 사용자 정의 동작을 구현하거나, 편집 환경을 개선하려면 커스텀 에디터를 사용해야 한다.

 

이를 통해 사용자는 에디터의 외관과 동작을 수정하거나 자신만의 사용자 정의 인터페이스를 만들 수 있다.


어떻게 사용할 수 있을까?

대부분의 커스텀 에디터와 관련된 API가 UnityEditor에 포함되어있다. 따라서 UnityEditor를 using 해준다. 또 필요에 따라 Editor클래스를 상속받을 필요가 있다.

 

에디터와 관련된 부분은 유저 인터페이스와 관련된 부분이므로 OnInspectorGUI()를 사용하는 경우가 대부분이지만 이번 포스팅에서는 애트리뷰트를 사용한 메뉴 아이템에 대해서 작성하였다.


메뉴 아이템

유니티의 MenuItem은 에디터에서 사용자 정의 메뉴 및 메뉴 항목을 생성하는 데 사용되는 애트리뷰트다.

MenuItem 어트리뷰트는 MonoBehaviour 클래스나 에디터 스크립트에서 메서드 위에 적용하여 해당 메서드를 메뉴 항목으로 사용할 수 있게 해 준다.

 

예를 들어, 아래의 스크립트는 선택된 오브젝트의 트랜스폼의 포지션을 원점으로 변경시켜 주는 메뉴 아이템이다.

(유니티는 포지션 리셋을 단축키로 제공하고 있지 않는데, 아래 스크립트를 사용하면 단축키로 사용 가능하다.)

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public static class Utility
{
    [MenuItem("Transform Utility/Reset Position %#r")]
    public static void TransformReset()
    {
        if (Selection.activeObject is GameObject data)
        {
            if (data.TryGetComponent(out Transform tp))
            {
                Undo.RecordObject(data.transform, data.name);
                tp.position = Vector3.zero;
                tp.rotation = Quaternion.identity;
            }
        }
    }
}

메뉴 아이템을 사용한 포지션 리셋

이제 위의 코드를 하나씩 분석해 보자.

 

1. [MenuItem("Transform Utility/Reset Position")]

이 애트리뷰트는 메인 메뉴 혹은 콘텍스트 메뉴에 함수를 추가해 주는 기능을 갖는다.

위의 애트리뷰트는 에디터에서 아래처럼 나타난다.

 

에디터의 상단 메뉴에 추가

 

2. [MenuItem("Transform Utility/Reset Position %#r")]

%#r은 해당 기능에 단축키를 부여한다.

앞에 공백(스페이스)이 있어야 단축키라는 것이 명시되기 때문에 이름 끝에 특정한 공백을 넣고 규칙을 작성해 넣어야 한다.

 

%(Ctrl), #(Shift), &(Alt), LEFT, RIGHT, UP, DOWN, F1 .. F12, HOME, END, PGUP, PGDN, INS, DEL, TAB, and SPACE 같은 특수문자들이 있다.

위의 메뉴 아이템의 경우는 %#r 이므로 Ctrl+R(shift r)이 단축키로 지정된다.

즉, 포지션을 원점으로 변경하는 작업을 컨트롤 쉬프트 R 단축키로 실행할 수 있게 된다.

 

3. Selection.activeObject

커스텀 에디터에서 아주 많이 사용되는 프로퍼티이다. 이 프로퍼티는 에디터에서 현재 선택된 오브젝트를 반환한다.

에디터에서 클릭한 오브젝트의 정보를 읽어 다양한 형태로 변환을 해도 된다.

 

4. Undo.RecordObject(Object, string);

이 함수는 Object를 Undo 시스템에 등록한다. 이 함수를 통해 등록을 해야만 변경사항이 저장되고, Ctrl+z를 눌러 되돌리기를 했을 때 이전 상태로 되돌아간다!

 


메뉴 아이템을 사용하면 마우스 위치로 레이를 발사하여 충돌된 위치에 오브젝트가 위치하도록 할 수도 있다.

[MenuItem("Transform Utility/Position To Mouse #t")]
public static void PositionToMouse()
{
    if (Selection.activeObject is GameObject data)
    {
        if (data.TryGetComponent(out Transform tp))
        {
            Undo.RecordObject(data.transform, data.name);

            var pos = Event.current.mousePosition;
            Ray ray = HandleUtility.GUIPointToWorldRay(pos - new Vector2(0, 45));
            if (Physics.Raycast(ray, out RaycastHit hitInfo))
            {
                tp.position = hitInfo.point;
            }
        }
    }
}

콜라이더와 충돌한 지점에 오브젝트 배치

반응형