以下のように記述している場合 Hierarchy にあるオブジェクトや Project にあるオブジェクト等
制限なく自由にオブジェクトの設定ができてしまう
[SerializeField]
private GameObject _obj;
そのため、オブジェクトに制限をかける Attribute を作成しました
制限は以下の3種類です
/// <summary> /// 子供のオブジェクトのみ /// </summary> [SerializeField, ObjectRestrict(TargetType.ChildOnly)] private GameObject _obj; /// <summary> /// Hierarchyのオブジェクトのみ /// </summary> [SerializeField, ObjectRestrict(TargetType.InHierarchy)] private GameObject _obj; /// <summary> /// Project リソースのみ /// </summary> [SerializeField, ObjectRestrict(TargetType.InProject)] private GameObject _obj;
コード
public enum TargetType { /// <summary> /// 子供のオブジェクトのみ /// </summary> ChildOnly, /// <summary> /// Hierarchyのオブジェクトのみ /// </summary> InHierarchy, /// <summary> /// Project リソースのみ /// </summary> InProject, } [AttributeUsage(AttributeTargets.Field)] public class ObjectRestrictAttribute : PropertyAttribute { public TargetType target { get; } public ObjectRestrictAttribute(TargetType type) { target = type; } } [CustomPropertyDrawer(typeof(ObjectRestrictAttribute))] public class NotNullDrawer : PropertyDrawer { private ObjectRestrictAttribute _attribute => attribute as ObjectRestrictAttribute; public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { position.height = base.GetPropertyHeight(property, label); using (var check = new EditorGUI.ChangeCheckScope()) { EditorGUI.PropertyField(position, property, label); if (check.changed && property.propertyType == SerializedPropertyType.ObjectReference) { if (!CanUpdateObject(property)) { property.objectReferenceValue = null; } } } } private bool CanUpdateObject(SerializedProperty property) { switch (_attribute.target) { case TargetType.ChildOnly: { var obj = property.serializedObject.targetObject as Component; var target = property.objectReferenceValue as GameObject; if (target == null || !target.activeInHierarchy) return false; return HasChildRecursive(obj.transform, target.transform); } case TargetType.InHierarchy: { var target = property.objectReferenceValue as GameObject; return target != null && target.activeInHierarchy; } case TargetType.InProject: { return !string.IsNullOrEmpty(AssetDatabase.GetAssetPath(property.objectReferenceValue)); } } return true; } private bool HasChildRecursive(Transform parent, Transform target) { foreach (Transform child in parent) { if (child.Equals(target)) return true; if (HasChildRecursive(child, target)) return true; } return false; } }