유니티 Custom Attributes 만들기! #사용자 지정 속성

유니티에는 다양한 Attribute가 존재합니다.

  1. HideInInspector: 스크립트의 공개 속성이라도 인스펙터에서 보이지 않게 할 수 있습니다.
  2. AddComponentMenu: 스크립트를 Unity의 컴포넌트 메뉴에 추가할 수 있습니다.
  3. ContextMenu: 스크립트의 메서드를 인스펙터의 컨텍스트 메뉴에 추가할 수 있습니다.
  4. CreateAssetMenu: 스크립트를 Unity의 에셋 메뉴에 추가할 수 있습니다.
  5. ExecuteInEditMode: 플레이 모드가 아닌 에디터 모드에서도 스크립트를 실행할 수 있습니다.
  6. RequireComponent: 스크립트가 특정 컴포넌트를 필요로 할 때, 그 컴포넌트를 자동으로 추가할 수 있습니다.
  7. Tooltip: 인스펙터에서 변수에 대한 설명을 표시할 수 있습니다.
  8. Range: 인스펙터에서 변수의 값을 특정 범위 내에서만 선택하도록 할 수 있습니다.
  9. SerializeField: 비공개 속성이라도 인스펙터에서 보이게 할 수 있습니다.
  10. Header: 인스펙터에서 변수 섹션에 헤더를 추가할 수 있습니다.

예시로 사용되는 어트리뷰트 예시는 아래 포스팅에서 확인해주세요!

 

유니티 CreateAssetMenu에 대하여

CreateAssetMenu란? CreateAssetMenu는 특정 스크립트에서 새로운 어셋을 생성할 수 있는 메뉴 옵션을 제공해줍니다. 이를 통해 사용자가 유니티 에디터의 메뉴를 통해 쉽게 새로운 인스턴스를 만들 수

wlsdn629.tistory.com

 

그럼 어트리뷰트를 사용하면 인스펙터를 꾸밀 수 있나요?

 

아닙니다! 어트리뷰트는 인스펙터를 꾸며주는 기능이 아니고 코드 요소에 메타데이터를 첨부하는 데 사용되는 클래스입니다. 사용자 지정 어트리뷰트를 만들려면 "Attribute" 클래스에서 직접 또는 간접적으로 상속되어야 합니다.

Attribute 상속

 


Custom Attributes 예제

Custom Attributes를 만들어서 Vector3 값을 슬라이드로 컨트롤 할 수 있게 만들어 보겠습니다!

 

아까도 말했다시피 Custom Attributes만으로는 인스펙터(에디터)를 수정할 수 없습니다. Editor스크립트와 함께 만들어보겠습니다.

using UnityEngine;

public class VectorRangeAttribute : PropertyAttribute
{
    public float Min { get; private set; }
    public float Max { get; private set; }

    public VectorRangeAttribute(float min, float max)
    {
        Min = min;
        Max = max;
    }
}

 

먼저, Attribute 클래스를 상속받아주는 Attribute클래스를 만들어줍니다.

Attribute를 이용해서 Min, Max값을 컨트롤 할 수 있도록 float변수를 만들어주었습니다.

 

#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(VectorRangeAttribute))]
public class VectorRangeDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        VectorRangeAttribute vectorSlider = (VectorRangeAttribute)attribute;

        if (property.propertyType == SerializedPropertyType.Vector2)
        {
            Vector2 newValue;
            newValue.x = EditorGUI.Slider(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), "x", property.vector2Value.x, vectorSlider.Min, vectorSlider.Max);
            newValue.y = EditorGUI.Slider(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight, position.width, EditorGUIUtility.singleLineHeight), "y", property.vector2Value.y, vectorSlider.Min, vectorSlider.Max);
            property.vector2Value = newValue;
        }
        else if (property.propertyType == SerializedPropertyType.Vector3)
        {
            Vector3 newValue;
            newValue.x = EditorGUI.Slider(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), "x", property.vector3Value.x, vectorSlider.Min, vectorSlider.Max);
            newValue.y = EditorGUI.Slider(new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight, position.width, EditorGUIUtility.singleLineHeight), "y", property.vector3Value.y, vectorSlider.Min, vectorSlider.Max);
            newValue.z = EditorGUI.Slider(new Rect(position.x, position.y + 2 * EditorGUIUtility.singleLineHeight, position.width, EditorGUIUtility.singleLineHeight), "z", property.vector3Value.z, vectorSlider.Min, vectorSlider.Max);
            property.vector3Value = newValue;
        }
        else
        {
            EditorGUI.LabelField(position, label, "Use only with Vector2 or Vector3");
        }
    }

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        if (property.propertyType == SerializedPropertyType.Vector2)
        {
            return EditorGUIUtility.singleLineHeight * 2;
        }
        else if (property.propertyType == SerializedPropertyType.Vector3)
        {
            return EditorGUIUtility.singleLineHeight * 3;
        }
        else
        {
            return EditorGUIUtility.singleLineHeight;
        }
    }
}
#endif

 

Editor스크립트를 만들어서 VectorRangeAttribute를 사용하는 클래스에서 Vector 값들을 슬라이드로 컨트롤 할 수 있도록 만들어주었습니다.

 

using UnityEngine;

public class AttributesTest : MonoBehaviour
{
    [VectorRange(0, 1)]
    [Header("VectorWithAttribute")]
    public Vector3 VectorWithAttribute;
    
    [Space(5)]
    [Header("-----------------------")]
    public Vector3 VectorWithNoAttribute;
}

 

마지막은 VectorRangeAttribute를 사용한 Vector와 VectorRangeAttribute를 사용하지 않은 Vector의 차이를 보기위한 테스트 클래스입니다.

 

모두 작성한 다음 빈 게임오브젝트를 하나 만들어준 후 AttributesTest를 붙여주겠습니다.

빠밤!

 

와우! 이제 Vector 값들을 슬라이드로 컨트롤 할 수 있게 되었습니다!

 


 

지금까지 Custom Attributes를 만드는 방법에 대해 알아보았습니다.

어떠신가요? 정말 놀랍지 않나요 ㅎㅎㅎ

 

다들 Custom Attributes를 이용해서 본인들이 제작하는 프로젝트에 필요한 유틸 기능들을 추가해보세요!

무작정 인스펙터를 꾸미는 용도로만 사용하지 마시고 정말 필요한 기능들을 자체 제작하여 팀의 능률을 올려보세요 ㅎㅎ!

 

인스펙터 꾸며주는 Custom Attributes는 Odin Inspector로 충분하답니다~!

 

유니티 Odin Inspector

Odin Inspector란? 오딘 인스펙터는 커스텀 에디터 코드를 한 줄도 작성하지 않고도 강력하고 사용자 친화적인 커스터마이징 에디터의 모든 워크플로 이점을 누릴 수 있는 Unity용 플러그인입니다.

wlsdn629.tistory.com