unity/유니티 기초

Unity - Button Attribute만들기

rimugiri 2024. 8. 21. 00:03
728x90

전에 타일맵을 생성하는 인스펙터 창을 제작하면서 이번에는 따로 인스펙터 창을 제작하지 않아도 간단하게 [Button]을 추가하면 인스펙터 창에서 실행할수 있도록 제작하려고 한다

 

결과

 

 

1. ButtonAttribute 만들기

using System;
using UnityEngine;

namespace PKW_Attributes
{
    public enum ButtonEnableMode
    {
        // 항상
        Always,
        // 에디터 상에서만
        Editor,
        // Playmode 상에서만
        Playmode
    }

    // 하나의 매소드를 대상으로 동작
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class ButtonAttribute : PropertyAttribute
    {
        public string ButtonName { get; }
        public ButtonEnableMode ButtonEnableMode { get; private set; }

        public ButtonAttribute(string buttonName = "", ButtonEnableMode ButtonEnableMode = ButtonEnableMode.Always)
        {
            this.ButtonName = buttonName;
            this.ButtonEnableMode = ButtonEnableMode;
        }
    }
}

 

2. 인스펙터창에 띄우기

using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace PKW_Attributes
{
    [CustomEditor(typeof(MonoBehaviour), true)]
    public class ButtonAttributeEditor : Editor
    {
        private MonoBehaviour monoBehaviour;
        private void OnEnable()
        {
            monoBehaviour = target as MonoBehaviour;
        }
        public override void OnInspectorGUI()
        {
            // 원래 존재하는 Inspector를 그린다
            DrawDefaultInspector();
			//base.OnInspectorGUI(); 를 사용해도 상관 없다
            
            // 모든 매소드를 확인해 본다
            MethodInfo[] methods = monoBehaviour.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            foreach (MethodInfo method in methods)
            {
                ButtonAttribute buttonAttribute = Attribute.GetCustomAttribute(method, typeof(ButtonAttribute)) as ButtonAttribute;

                if (buttonAttribute != null)
                {
                    // 버튼 이름 설정
                    string buttonLabel = string.IsNullOrEmpty(buttonAttribute.ButtonName) ? method.Name : buttonAttribute.ButtonName;

                    if (GUILayout.Button(buttonLabel))
                    {
                        method.Invoke(monoBehaviour, null);
                    }
                }
            }
        }
    }
}

 

3. TestCode

using UnityEngine;

namespace PKW_Attributes
{
    public class ButtonAttributeTest : MonoBehaviour
    {
        public int testInt = 0;

        [Button("TestMethod")]
        public void TestMethod()
        {
            Debug.Log("TestMethod");
        }

        public void TestMethod2()
        {
            Debug.Log("TestMethod2");
        }

        [Button("TestMethod3")]
        public void TestMethod3()
        {
            testInt++;
            Debug.Log("TestMethod3");
        }
    }
}
728x90