ObjectField functions ignoring parameter

I’m attempting to use the SerialzedProperty versions of the EditorGUILayout.ObjectField function to display a custom ScriptableObject, but it ignores me when I try to specify the object’s type.

  • Background/details:

The custom ScriptableObject implements inheritance; a BaseClass (derived from ScriptableObject), with two other classes derived from that (DerivedClassA, and DerivedClassB).

In my editor code, the SerializedProperty I’m trying to draw references a member of the sample MonoBehaviour. This member is declared (but not instantiated) as a BaseClass.

  • Main issue:

In my editor code, I will use some logic to determine if I want to allow the user to select one or the other of the derived classes. (In the sample below, I just display them all, as tests)

Unfortunately, when I use the SerializedProperty version of the ObjectField function, that takes a Type as a parameter, the type parameter is ignored.

  • Other tests:

However, If I used the Object (rather than the SerializedProperty) versions of the ObjectFiled function, it DOES use the Type parameter properly.

  • Question:

Am I doing something wrong? Why does the ObjectField function ignore the provided parameter when I use the SerializedProperty version?

  • Code:

Here is my test project’s code. It is the editor file, at the bottom, that contains the problematic function calls. You can use the menu items to create test objects of each derived class, in the project folder, if you want to try it out. I’m also attaching a “package” (zipped), so no need to copy/paste, if you want to try it out.

[104296-objectfields.zip|104296]

BaseClass.cs

using UnityEngine;

public class BaseClass : ScriptableObject {

    public int anInt;
}

DerivedClassA.cs

using UnityEditor;

public class DerivedClassA : BaseClass {

    public float aFloat;

    
    [MenuItem("GameObject/MyCategory/DerivedClassA Object", false, 10)]
    static void CreateCustomDerivedClassA(MenuCommand menuCommand)
    {
        // Create a custom game object
        DerivedClassA instance = DerivedClassA.CreateInstance<DerivedClassA>();
        AssetDatabase.CreateAsset(instance, "Assets/MyDerivedClassA.mat");

    }
}

DerivedClassB.cs

using UnityEditor;

public class DerivedClassB : BaseClass {

    public string aString = "a";
    [MenuItem("GameObject/MyCategory/DerivedClassB Object", false, 10)]
    static void CreateCustomDerivedClassA(MenuCommand menuCommand)
    {
        // Create a custom game object
        DerivedClassB instance = DerivedClassB.CreateInstance<DerivedClassB>();
        AssetDatabase.CreateAsset(instance, "Assets/MyDerivedClassB.mat");

    }
}

HoldingMono.cs

using UnityEngine;

public class HoldingMono : MonoBehaviour {
    public BaseClass baseClass;
}

HoldingMonoEditor.cs

using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(HoldingMono))]
public class HoldingMonoEditor : Editor
{

    SerializedProperty baseClassProperty;

    void OnEnable()
    {
        baseClassProperty = serializedObject.FindProperty("baseClass");
    }

    public override void OnInspectorGUI()
    {
        EditorGUILayout.ObjectField(baseClassProperty, typeof(DerivedClassA));// allows selection of any BaseClass objects, and shows the type BaseClass when empty
        EditorGUILayout.ObjectField(baseClassProperty, typeof(DerivedClassB));// allows selection of any BaseClass objects, and shows the type BaseClass when empty

        baseClassProperty.objectReferenceValue=EditorGUILayout.ObjectField(new GUIContent("DerivedClassA"),baseClassProperty.objectReferenceValue, typeof(DerivedClassA),false);// allows selection of only DerivedClassA objects, and shows the type DerivedClassA whgen empty
        baseClassProperty.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent("DerivedClassB"), baseClassProperty.objectReferenceValue, typeof(DerivedClassB), false);// allows selection of only DerivedClassB objects, and shows the type DerivedClassB when empty

    }
}

Yes, the Type parameter is in fact ignored. Have a look at this:

private static void ObjectFieldInternal(Rect position, SerializedProperty property, Type objType, GUIContent label, GUIStyle style)
{
	int controlID = GUIUtility.GetControlID(EditorGUI.s_PPtrHash, FocusType.Keyboard, position);
	position = EditorGUI.PrefixLabel(position, controlID, label);
	bool allowSceneObjects = false;
	if (property != null)
	{
		Object targetObject = property.serializedObject.targetObject;
		if (targetObject != null && !EditorUtility.IsPersistent(targetObject))
		{
			allowSceneObjects = true;
		}
	}
	EditorGUI.DoObjectField(position, position, controlID, null, null, property, null, allowSceneObjects, style);
}

As you can see the “objType” parameter is not used here. It should have been passed instead of the “null” infront of the property parameter in the last line. The first null is an UnityEngine.Object reference. The method DoObjectsField is actually used by all ObjectField methods. So either “property” is null or that object reference is null.

So you can probably call it a bug. Note that i don’t use the latest Unity version but that’s how it looks like in “Unity 5.6.1f1”. The SerializedProperty version of ObjectField is actually relative new. It already existed as internal methods but those didn’t have a Type argument. So it’s probably a copy&paste error. File a bugreport and get it fixed in a year ^^