유니티 ShowIfComponent Attribute 만들어보기 #특정 컴포넌트를 가지고 있을 때 보여지게

 

 

유니티 Odin Inspector

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

wlsdn629.tistory.com

ShowIf 어트리뷰트는 오딘 인스펙터에 있는 기능이긴 합니다.

ShowIf 어트리뷰트를 사용하면 특정 컴포넌트의 조건에 따라 특정 필드를 보이게 할지 말 지를 컨트롤 할 수 있습니다.

 

저는 ShowIf 어트리뷰트를 응용해서 ShowIfComponent 어트리뷰트를 만들어보았습니다.

ShowIfComponent 어트리뷰트를 사용하면 특정 컴포넌트를 가지고 있을 때에만 해당 필드가 보여지게 할 수 있습니다.


ShowIfComponent Attribute 코드

(좌) 특정 컴포넌트가 존재할 시 인스펙터에 노출되는 모습 / (우) 컴포넌트가 존재하지 않아 노출되지 않는 모습

 

Custom Attribute 제작 방법은 아래 포스팅을 참고해주세요.

 

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

유니티에는 다양한 Attribute가 존재합니다. HideInInspector: 스크립트의 공개 속성이라도 인스펙터에서 보이지 않게 할 수 있습니다. AddComponentMenu: 스크립트를 Unity의 컴포넌트 메뉴에 추가할 수 있습

wlsdn629.tistory.com

 

using UnityEngine;

public class ShowIfComponentAttribute : PropertyAttribute
{
    public string ComponentName { get; private set; }

    public ShowIfComponentAttribute(string componentName)
    {
        ComponentName = componentName;
    }
}

 

#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(ShowIfComponentAttribute))]
public class ShowIfDrawer : PropertyDrawer
{
    private readonly Dictionary<string, Type> componentTypeCache = new ();

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        if (ShouldShow(property))
        {
            EditorGUI.PropertyField(position, property, label, true);
        }
    }

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return ShouldShow(property) ? EditorGUI.GetPropertyHeight(property, label, true) : 0f;
    }

    private bool ShouldShow(SerializedProperty property)
    {
        ShowIfComponentAttribute showIfComponent = (ShowIfComponentAttribute)attribute;
        Component targetComponent = property.serializedObject.targetObject as Component;

        Type componentType = GetComponentType(showIfComponent.ComponentName);

        return componentType != null &&
               (targetComponent?.GetComponent(componentType) != null ||
                targetComponent?.GetComponentInChildren(componentType) != null);
    }

    private Type GetComponentType(string componentName)
    {
        if (componentTypeCache.TryGetValue(componentName, out Type cachedType))
        {
            return cachedType;
        }

        foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
        {
            var componentType = assembly.GetTypes().FirstOrDefault(t => t.Name == componentName);
            if (componentType != null)
            {
                componentTypeCache[componentName] = componentType;
                return componentType;
            }
        }

        return null;
    }
}
#endif

 


ShowIfComponent 사용방법

  [ShowIfComponent("InteractableUnityEventWrapper")] public bool SetOwnerOnGrab = false;

 

이렇게 사용하면 ~EventWrapper 컴포넌트가 null이 아닌 경우 SetOwnerOnGrab 필드가 인스펙터에 노출됩니다.