Last active
May 28, 2020 12:54
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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