Skip to content

Instantly share code, notes, and snippets.

@h-sigma
Last active May 28, 2020 12:54
Show Gist options
  • Save h-sigma/82d19801b072e57d1044ec5c92f29efc to your computer and use it in GitHub Desktop.
Save h-sigma/82d19801b072e57d1044ec5c92f29efc to your computer and use it in GitHub Desktop.
An attribute for MonoBehaviour's that restricts assigning in the editor to MB's deriving from a specific interface.
/*
* Author: Harshdeep Singh, https://github.com/h-sigma
* Year: 2020
* Description: An attribute for MonoBehaviour's that restricts assigning in the editor to MB's deriving from a specific interface.
* Use:
* [Interface(typeof<IHealth>)]
* public MonoBehaviour health;
* Note: This hasn't been bug tested, and it is a very simplistic way to do the job. If required or requested, I may choose to improve it.
*/
//place this in regular scripts directory
public class InterfaceAttribute : PropertyAttribute
{
public Type interfaceType;
public InterfaceAttribute(Type interfaceType)
{
this.interfaceType = interfaceType;
}
}
using System;
using UnityEditor;
using UnityEngine;
using Object = System.Object;
//place this in an Editor folder
[CustomPropertyDrawer(typeof(InterfaceAttribute))]
public class InterfaceAttributePropertyDrawer : PropertyDrawer
{
private InterfaceAttribute attr;
private Type type => attr.interfaceType;
private MonoBehaviour linkedMb;
public override void OnGUI(Rect position, SerializedProperty property,
GUIContent label)
{
attr = attribute as InterfaceAttribute;
if (attr == null || type == null) return;
var mb = property.objectReferenceValue;
var obj = FetchMonobehaviour(mb);
EditorGUI.BeginChangeCheck();
GameObject gameobj = obj == null ? null : obj.gameObject;
var l = gameobj == null ? property.displayName : property.displayName + $" ({obj.GetType().Name})";
if(EditorUtility.IsPersistent(property.serializedObject.targetObject))
gameobj = EditorGUI.ObjectField(position, l, gameobj, typeof(GameObject),
false) as GameObject;
else
gameobj = EditorGUI.ObjectField(position, l, gameobj, typeof(GameObject),
true) as GameObject;
if (EditorGUI.EndChangeCheck())
{
property.objectReferenceValue = FetchMonobehaviour(gameobj);
}
}
private MonoBehaviour FetchMonobehaviour(UnityEngine.Object obj)
{
if (obj == null) return null;
switch (obj)
{
case MonoBehaviour mb:
if (type.IsInstanceOfType(mb))
return mb;
else
return null;
case GameObject gameObject:
var candidate = gameObject.GetComponent(type) as MonoBehaviour;
return candidate;
default:
return null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment