How to configure a PropertyField so it won't allow scene objects

My MonoBehaviour has a field

public GameObject targetPrefab;

I am writing a custom inspector and would like the user to only be able to drag assets to this field, NOT scene objects. I EditorGUILayout has ObjectField which has a flag for disallowing scene objects:

target.targetPrefab = (GameObject) EditorGUILayout.ObjectField(“Target Prefab”,
target.targetPrefab,
typeof(GameObject),
false);

I would like to use:

so = new SerializedObject(target);
targ = so.FindProperty("targetPrefab");
EditorGUILayout.PropertyField(targ);

However I can’t find a way of disallowing scene objects from being dragged to the PropertyField. Is there a way?

Thanks.

Unity 4.3.4 is here, and there’s still no parameter you could pass to PropertyField to disallow dropping scene objects.

If you have ILSpy or .NET reflector, you could inspect PropertyField yourself to see how it’s implemented. As you might have guessed, PropertyField has a switch statement internally so that it picks the right field type to use, based on your property. Here’s the part related to when the property’s type is a reference type:

  case SerializedPropertyType.ObjectReference:
                ObjectField(position, property, label);

Here’s that ObjectField:

internal static void ObjectField(Rect position, SerializedProperty property, GUIContent label)
{
    ObjectField(position, property, label, EditorStyles.objectField);
}

Follow along:

internal static void ObjectField(Rect position, SerializedProperty property, GUIContent label, GUIStyle style)
{
    int id = GUIUtility.GetControlID(s_PPtrHash, EditorGUIUtility.native, position);
    position = PrefixLabel(position, id, label);
    bool allowSceneObjects = false;
    if (property != null)
    {
        Object targetObject = property.serializedObject.targetObject;
        if ((targetObject != null) && !EditorUtility.IsPersistent(targetObject))
        {
            allowSceneObjects = true;
        }
    }
    DoObjectField(position, position, id, null, null, property, null, allowSceneObjects, style);
}

So at the end it’s using that DoObjectField, which is essentially the same method used in EditorGUILayout.ObjectField (if you follow that along, you’ll end up with DoObjectField as well) - As you can see allowSceneObjects is being set internally which sucks :frowning:

You could always fallback and use EditorGUILayout.ObjectField and set your object directly. But before that you have to Undo.RecordObject(yourObject, "Some title"); if you want undo support.

If there’s a solution to setting allowSceneObjects yourself for PropertyField then it’s gonna be a hack, definitely a hack.

I know the question is a bit old, but i stumbled upon the same problem and found a workaround. Maybe it is not elegant, but works. I’ll write it here, because this question is #1 in Google if you look for this problem.

The idea is to check in the Editor script if the reference provided is from a prefab. If not, the previous reference has to be restored. This is an example code:

[CustomEditor(typeof(ModelAvatarGenerator), false)]
public class CustomModelAvatarEditor : Editor
{
    #region Serialized Properties
    
    /// <summary>
    /// Serialized property of fbxModel of target
    /// </summary>
    private SerializedProperty m_fbxModel;
    
    #endregion
    
    public void OnEnable()
    {
        m_fbxModel = serializedObject.FindProperty("fbxModel");
    }
    
    /// <summary>
    /// Executed at script displaying
    /// </summary>
    public override void OnInspectorGUI()
    {
        serializedObject.Update();
    
        //holds label and tooltip of each control
        GUIContent labelTooltip;
    
        //Custom Avatar Model (remember to force the user to insert only prefabs instances)
        GUILayout.BeginVertical();
        labelTooltip = new GUIContent("Model Avatar", "Model to use as user avatar");
        GameObject oldReference = (GameObject)m_fbxModel.objectReferenceValue; //save current avatar reference
        EditorGUILayout.PropertyField(m_fbxModel, labelTooltip);
    
        if ((GameObject)m_fbxModel.objectReferenceValue != null) //to allow null (None) to be used as a correct value
        {
            PrefabType avatarPrefabType = PrefabUtility.GetPrefabType((GameObject)m_fbxModel.objectReferenceValue); //get its prefab type
    
            if(avatarPrefabType != PrefabType.ModelPrefab && avatarPrefabType != PrefabType.Prefab) //if it is not a prefab on disk, restore previous reference
            {
                m_fbxModel.objectReferenceValue = oldReference;
            }
        }
    
        GUILayout.EndVertical();
    
        serializedObject.ApplyModifiedProperties();
    }
    
}

Hope this helps! Happy coding :wink: