うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【Unity】自動で GetCompoent をする Attribute【PropertyAttribute】

コンポーネントが必要な場合 RequireComponentReset()
コンポーネントの取得処理を書く必要がありますが、毎度書くのが面倒だというときがあり、
PropertyAttribute で解決できるのではと思い作成してみました

using UnityEngine;
 
[RequireComponent(typeof(SpriteRenderer))]
public class Sample : MonoBehaviour
{
    [SerializeField]
    private SpriteRenderer _spriteRenderer;
 
    private void Reset()
    {
        _spriteRenderer = GetComponent<SpriteRenderer>();
        if (_spriteRenderer == null)
            _spriteRenderer = gameObject.AddComponent<SpriteRenderer>();
    }
}

コード

SerializedProperty の Type 取得には以前の記事で紹介したこちらをご利用ください
【Unity】SerializedProperty の Type や FieldInfo を取得する - うにてぃブログ

using System;
using UnityEditor;
using UnityEngine;

public class AddComponentAttribute : PropertyAttribute
{
}

#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(AddComponentAttribute))]
public class AddComponentPropertyDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EditorGUI.PropertyField(position, property, label);

        if (property.propertyType != SerializedPropertyType.ObjectReference)
            return;

        if (property.objectReferenceValue != null)
            return;

        var type = SerializedPropertyUtility.GetPropertyType(property);
        if (!type.IsSubclassOf(typeof(Component)))
            return;

        var comp = property.serializedObject.targetObject as Component;
        if (comp == null)
            return;

        var addc = comp.gameObject.GetComponent(type);
        property.objectReferenceValue = addc != null ? addc : comp.gameObject.AddComponent(type);
    }
}
#endif

動作テスト

コンポーネントをアタッチしたタイミングで、
AddComponentAttribute がついているコンポーネントを追加できています

f:id:hacchi_man:20200319010311g:plain

using UnityEngine;

public class SampleMonoBehaviour : MonoBehaviour
{
    [SerializeField, AddComponent]
    private SpriteRenderer _spriteRenderer;

    [SerializeField, AddComponent]
    private BoxCollider _boxCollider;
}