Search Unity

How do I get the Child Type in a PropertyDrawer of Parent Type

Discussion in 'Scripting' started by darkwingfart, May 4, 2022.

  1. darkwingfart

    darkwingfart

    Joined:
    Oct 13, 2018
    Posts:
    78
    How do I get the CHILD TYPE without try:catch and without making a parameter in the parent?

    I am implementing an abstract class.
    Code (CSharp):
    1.     //parent
    2.     public abstract class StatBase : ScriptableObject
    3.     //children
    4.     public class StatBool : StatBase
    5.     ...
    6.     public class StatRange : StatBase
    I have a PropertyDrawer that as you can see it is set to work for children.
    Code (CSharp):
    1.     [CustomPropertyDrawer(typeof(StatBase), true)]
    2.     public class StatPropertyDrawer : PropertyDrawer
    That I'm using for an array of type StatBase.
    Code (CSharp):
    1.     public class Stats
    2.     {
    3.         public StatBase[] List;
    4.  
    I've tried everything I can think of to get the --Child Type-- so I can do different layouts for them and all I've come up with is trying to cast the objectReferenceValue.
    Code (CSharp):
    1.  
    2.             //RANGE
    3.             Type type = null;
    4.             try {
    5.                 StatRange range = (StatRange)prop.objectReferenceValue;
    6.                 type = range.GetType();
    7.             } catch {
    8.             }
    In my CustomEditor I don't have this problem.
     
  2. darkwingfart

    darkwingfart

    Joined:
    Oct 13, 2018
    Posts:
    78
    As you can see with the default PropertyDrawer the Child Type is shown. I can't seem to figure out how to get that Child Type in my custom PropertyDrawer.
    upload_2022-5-3_20-46-58.png
     
  3. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,993
    There should be no need for a try catch. However you have to do a null check of course. If you don't, calling GetType on null would throw a null reference exception. Unity's ObjectField essentially looks like this. Down in the repaint handling section it chooses the content to display. As you can see here it first seperates what to display based on if we supplied a SerializedProperty or just an Object reference or both. It then uses the internal ObjectContent method to get the string that should be displayed.

    The used "GetTypeNameWithInfo" method is an external method that is defined in native C++ code. However it most likely does a similar thing, though on the native side it may be simpler / faster to access the type name.

    You don't really need to cast the objectReference to StatRange unless you need it as StatRange for some other reason. You can call GetType on any object reference as long as it is not null.
     
  4. darkwingfart

    darkwingfart

    Joined:
    Oct 13, 2018
    Posts:
    78
    This is one of those questions where I know I tried the thing that ended up working.

    It works now. No idea why it didn't work before.
    Code (CSharp):
    1. prop.objectReferenceValue.GetType() == typeof(StatRange)
     
  5. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,993
    Where do you use this line? This line has the same problems I already mentioned. In case the reference is null, you would get a null reference exception. Again, you should test for null one way or the other.

    You usually shouldn't use GetType if you want to do a type check. This is all part of reflection. To see if an object is of a certain type, you usually use the "is" operator
    Code (CSharp):
    1. if (prop.objectReferenceValue is StatRange)
    Though a null check is still necessary because when a reference object is destroyed, it still exists as a missing reference but can't be used anymore. An ObjectField can contain no reference, a null value, so you have to handle that in some way.
     
  6. darkwingfart

    darkwingfart

    Joined:
    Oct 13, 2018
    Posts:
    78
    Yeah... I'm checking for a null. I didn't post all my code because I feel posting huge amounts of code is the most obnoxious S***. Often people don't even read critically enough to be helpful so I try to be concise.

    Using "is" is functionally identical to "GetType() == typeof(" but the "is" notation is simpler so I'll check it out thanks.