Skip to content

Instantly share code, notes, and snippets.

@AsherVo
Last active October 26, 2020 04:03
Show Gist options
  • Save AsherVo/5ee0cdc5f2696fe2d528070f23562394 to your computer and use it in GitHub Desktop.
Save AsherVo/5ee0cdc5f2696fe2d528070f23562394 to your computer and use it in GitHub Desktop.
Using unity's standard ObjectField in RequireReferenceDrawer to fix bugs and improve prefab workflow.
// PLEASE NOTE: This will add ~1sec to your save time
// If that is unacceptable (which it was to me), then you can change all the
// references to "MonoBehaviour" in this file to your own custom behaviour type
// that this script will search through each time you save
using UnityEditor;
using UnityEngine;
using System.Linq;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using UnityEditor.Experimental.SceneManagement;
public class RequireReferenceAlert : UnityEditor.AssetModificationProcessor
{
static string[] OnWillSaveAssets(string[] paths)
{
bool doValidate = false;
foreach ( string path in paths )
{
if ( path.Contains( ".prefab" ) || path.Contains( ".scene" ) )
{
doValidate = true;
break;
}
}
if ( !doValidate )
return paths;
MonoBehaviour[] allBehaviours;
PrefabStage stage = PrefabStageUtility.GetCurrentPrefabStage();
if ( stage != null )
{
List< MonoBehaviour > foundBehaviours = new List< MonoBehaviour >();
GameObject[] rootObjects = stage.scene.GetRootGameObjects();
foreach ( GameObject rootObj in rootObjects )
foundBehaviours.AddRange( rootObj.GetComponentsInChildren< MonoBehaviour >( true ) );
allBehaviours = foundBehaviours.ToArray();
}
else
{
allBehaviours = Object.FindObjectsOfType< MonoBehaviour >();
}
foreach ( MonoBehaviour b in allBehaviours )
{
FieldInfo[] fields = b.GetType().GetFields();
foreach ( FieldInfo field in fields )
{
object[] attrs = field.GetCustomAttributes( true );
foreach ( object attr in attrs )
{
if ( attr is RequireReferenceAttribute )
{
object obj = field.GetValue( b ) as object;
if ( obj is IEnumerable && obj.GetType().IsGenericType )
{
IEnumerable listObj = obj as IEnumerable;
foreach ( Object o in listObj )
{
if ( IsNullShowWarning( o, b.ToString(), b) )
return new string[ 0 ];
}
}
else
{
if ( IsNullShowWarning( obj, b.ToString(), b ) )
return new string[ 0 ];
}
break;
}
}
}
}
return paths;
}
static bool IsNullShowWarning ( object obj, string name, Object selectObject )
{
if ( obj == null )
{
Selection.activeObject = selectObject;
return !EditorUtility.DisplayDialog(
"Missing References",
$"The following component is missing some required references: {name}",
"Save Anyway",
"Cancel"
);
}
return false;
}
}
public class RequireReferenceAttribute : PropertyAttribute
{
public RequireReferenceAttribute ()
{
}
}
using UnityEditor;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
[CustomPropertyDrawer(typeof(RequireReferenceAttribute))]
public class RequireReferenceDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
EditorGUI.ObjectField( position, property );
if ( property.objectReferenceValue == null )
{
EditorGUI.DrawRect( position, new Color( 1.0f, 0.0f, 0.0f, 0.5f ) );
}
EditorGUI.EndProperty();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment