Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Glurth · Oct 23, 2017 at 09:26 PM · editortypeserializedpropertyobject referenceobjectfield

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.

link text

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
 
     }
 }


objectfields.zip (2.2 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by Bunny83 · Oct 23, 2017 at 09:53 PM

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 ^^

Comment
Add comment · Show 11 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Oct 23, 2017 at 09:56 PM 0
Share

The reason why the "UnityEngine.Object" version works is that it directly uses DoObjectField like this:

 public static Object ObjectField(Rect position, Object obj, Type objType, bool allowSceneObjects)
 {
     int controlID = GUIUtility.GetControlID(EditorGUI.s_ObjectFieldHash, FocusType.$$anonymous$$eyboard, position);
     return EditorGUI.DoObjectField(EditorGUI.IndentedRect(position), EditorGUI.IndentedRect(position), controlID, obj, objType, null, null, allowSceneObjects);
 }

avatar image Glurth · Oct 23, 2017 at 10:48 PM 0
Share

Thanks, Bunny! Bug submission complete: https://fogbugz.unity3d.com/default.asp?961878_20mllpnjoe3393ne @Adam-$$anonymous$$echtley FYI

avatar image Bunny83 Glurth · Oct 24, 2017 at 12:55 AM 0
Share

As a temporary workaround you could use this reflection solution. Unfortunately it's not possible to create a delegate for the method (to improve performance and avoid garbage) since that "ObjectFieldValidator" is an internal type and you can't create a delegate that would be compatible with the methods parameter list.

Though I cached as much as possible. Since Unity's Rect struct has a Set method we can even avoid boxing the position all the time by simply creating a delegate for a single boxed value that is reused each time. The only thing that can't be avoided is the single boxed "int" for the controlID as there's no way to set a boxed integer value to another value without re-boxing the value again.

$$anonymous$$aybe it got a bit too far with the optimisations, but it seems to work ^^

avatar image Glurth Bunny83 · Oct 24, 2017 at 01:57 AM 0
Share

So that solution basically replaces the bugged version, and invokes the internal DoObjectField itself? Nice!

Show more comments
Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

94 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How to Find Assets of the Same Type in Editor Script 1 Answer

Make a PropertyField() for a Texture2D SerializedProperty looking like an ObjectField() 2 Answers

EditorGUILayout.ObjectField for Array 1 Answer

why I Cant Add Multiple Objects to the "Object Field" in Editor Window? 3 Answers

Display Custom Inspectors for each class in a List<> 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges