• 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 /
  • Help Room /
avatar image
0
Question by GUSRG · Jun 19 at 01:37 PM · editorunityeditorinspector

Access Array Classes using Custom Editor

Hello everyone. I'm quite new to the Custom Editor script and I'm looking for a quick help.

I want to hide some variables using an Enum. And so far I managed to do so. Problem is, when the variables are inside another class.

To show this, I made those two scripts, the main script and the Editor script:

Inspector image: https://imgur.com/SjKDOSh

JustExample.cs (main script):

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class JustExample : MonoBehaviour
 {
     public enum Selector 
     {
         Green,
         Red
     }
 
     public Selector selector;
     [HideInInspector]
     public bool iCanHideThisIfRed;
     public Data[] data;
 }
 
 [System.Serializable]
 public class Data
 {
     public string text;
     public int Green; //need to hide/show this
     public int Red;  //need to hide/show this
 }

The JustExampleEditor.cs (Editor class):

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEditor;
 
 [CustomEditor(typeof(JustExample))]
 public class JustExampleEditor : Editor
 {
     public override void OnInspectorGUI()
     {
         JustExample justExample = (JustExample)target;
 
         EditorGUILayout.PropertyField(serializedObject.FindProperty("selector"));
 
         if (justExample.selector == JustExample.Selector.Red)
         {
             //I want to access the variables inside "data" here, to hide one field
         }
 
         else if (justExample.selector == JustExample.Selector.Green) 
         {
             EditorGUILayout.PropertyField(serializedObject.FindProperty("iCanHideThisIfRed"));
             //I want to access the variables inside "data" here, to hide one field
         }
 
         EditorGUILayout.PropertyField(serializedObject.FindProperty("data"));
         serializedObject.ApplyModifiedProperties();
 
 
         //base.OnInspectorGUI();
     }
 }
 
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
1
Best Answer

Answer by oscarAbraham · Jun 22 at 12:14 AM

The main problem in your case is not with access to fields in another class; the main problem is that the instances of those classes are inside an array. Controlling the drawing of a nested field is relatively easy. The thing is that you want the things that Unity draws around arrays, so we can't just draw each field from the array manually; we need to let Unity control the drawing of that particular array.

What we can do is create a PropertyDrawer for the Data class. It will let Unity control the drawing of the whole array, but it will let us take control of the drawing of each element drawn inside that array. We'll need a way to communicate between the Custom Editor and the Property Drawer; we'll use a static variable for that. Here's an idea of how the Property drawer would look like:

 [CustomPropertyDrawer(typeof(DataDrawer))]
 public class DataDrawer : PropertyDrawer
 {
     // This static field should be set before any DataDrawer is used.
     public static JustExample.Selector currentSelector;
 
     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
     {
         // We can't use GUILayout in propery drawers; we need to calculate each field's position.
         // The position we received should contain all the fields in our class; it uses the height
         // returned by GetPropertyHeight. We'll use it to calculate the position of each field.
         var textFieldPosition = position;
         textFieldPosition.height = EditorGUIUtility.singleLineHeight;
         EditorGUI.PropertyField(position, property.FindPropertyRelative("text"));
 
         var specialFieldPosition = position;
         specialFieldPosition.height = EditorGUIUtility.singleLineHeight;
         // The next position is moved in y after the previous one, plus some spacing.
         specialFieldPosition.y = textFieldPosition.yMax + EditorGUIUtility.standardVerticalSpacing;
 
         if (currentSelector == JustExample.Selector.Green)
         {
             EditorGUI.PropertyField(specialFieldPosition, property.FindPropertyRelative("Green"));
         }
         else if (currentSelector == JustExample.Selector.Red)
         {
             EditorGUI.PropertyField(specialFieldPosition, property.FindPropertyRelative("Red"));
         }
     }
 
     public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
     {
         // Here you should return the height needed for the fields displayed for the current mode.
         // In this example, we always use two lines for two fields plus a space between them.
         return (EditorGUIUtility.singleLineHeight * 2) + EditorGUIUtility.standardVerticalSpacing;
     }
 }


And here's how the Custom Editor would communicate with it by setting its static field before drawing the array:

 [CustomEditor(typeof(JustExample))]
 public class JustExampleEditor : Editor
 {
     public override void OnInspectorGUI()
     {
         JustExample justExample = (JustExample)target;
 
         EditorGUILayout.PropertyField(serializedObject.FindProperty("selector"));
 
         if (justExample.selector == JustExample.Selector.Green)
         {
             EditorGUILayout.PropertyField(serializedObject.FindProperty("iCanHideThisIfRed"));
         }
 
         // We set the currentSelector field so all the data drawers that will be used when
         // drawing the PropertyField for "data" know which fields should be hidden.
         DataDrawer.currentSelector = justExample.selector;
         EditorGUILayout.PropertyField(serializedObject.FindProperty("data"));
         serializedObject.ApplyModifiedProperties();
     }
 }
Comment
Add comment · Show 10 · 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 GUSRG · Jun 22 at 01:24 AM 0
Share

Thanks for answering Oscar.

I tried both ways, but I get the following error on both:

https://imgur.com/2BwxkZL

Code:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEditor;
 
 [CustomEditor(typeof(JustExample))]
 public class JustExampleEditor : Editor
 {
     SerializedProperty selectorProp;
     SerializedProperty redProp;
     SerializedProperty greenProp;
 
     private void OnEnable()
     {
         selectorProp = serializedObject.FindProperty("selector");
         redProp = serializedObject.FindProperty("data.Red");
         greenProp = serializedObject.FindProperty("data.Green");
     }
     public override void OnInspectorGUI()
     {
         
         JustExample justExample = (JustExample)target;
 
         EditorGUILayout.PropertyField(serializedObject.FindProperty("selector"));
         var dataProp = serializedObject.FindProperty("data");
 
         if (justExample.selector == JustExample.Selector.Red)
         {
             //I want to access the variables inside "data" here, o hide one field
             EditorGUILayout.PropertyField(dataProp.FindPropertyRelative("Red"));
         }
 
         else if (justExample.selector == JustExample.Selector.Green) 
         {
             EditorGUILayout.PropertyField(serializedObject.FindProperty("iCanHideThisIfRed"));
             EditorGUILayout.PropertyField(dataProp.FindPropertyRelative("Green"));
             //I want to access the variables inside "data" here, to hide one field
         }
 
         
         serializedObject.ApplyModifiedProperties();
 
 
         //base.OnInspectorGUI();
     }
 }
 

avatar image oscarAbraham GUSRG · Jun 22 at 02:36 AM 0
Share

Right, sorry, I didn't realize your data property is an array. I should have realized it; it's right in the title. For a short answer, you can access a child property in an array element like this:

 var dataProp = serializedObject.FindProperty("data");
 // Draw a field to change the size of the array:
 EditorGUILayout.PropertyField(dataProp.FindPropertyRelative("Array.size");
 
 // Loop through all the elements in the data array.
 for (int i = 0; i <= dataProp.ArraySize; i++)
 {
     // Use "Red" or "Green" depending on the selector's value.
     // This is one way to access the child property:
     var childProp = dataProp.GetArrayElementAtIndex(i).FindPropertyRelative("Red");
 
     // This is another way (The second "data" word is just the same by coincidence;
     // you'd still use data there if your field had another name) :
     var childProp = serializedObject.FindProperty($"data.Array.data[{i}].Red");
     
     // Then you just draw it:
     EditorGUILayout.PropertyField(childProp);
 }


I imagine that you'd want to show the contents of the array in a reorderable list, though. Am I right? There are two main ways of doing that; one way is using a PropertyDrawer and another is drawing the ReorderableList directly without PropertyField. Both are quit a bit more complex than the answer I gave. I'll update the answer with one of those ways if that's okay with you. :).

To know which one I should describe, could you tell me a bit more about your actual use case? I specially need to know if you are using this custom Data class in more than one different component, or if it's used in only one specific Script. The more you tell me about your use case, the better I can help you, though.

EDIT
Also, depending on your use case, you might want to consider using a struct for Data instead of class. They are usually better for performance in this kind of cases.

avatar image GUSRG oscarAbraham · Jun 22 at 01:41 PM 0
Share

Hello again oscar.

Thanks once more.

I imagine that you'd want to show the contents of the array in a reorderable list, though. Am I right?


Yes, since some of the fields are only going to be used when the correct enum is selected, I decided to hide unused those fields to keep the Inspector clear and better to read.

(I know it's just a example with Green and Red, but I plan to use this with more fields later on, so I kept simple)

Btw, the example you gave me works, now I can access the Red and Green fields.

But they are showing outside of the Data elements: https://imgur.com/UG6n9yu Do you know how to make they appear inside the Data?

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.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

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

Variables In Editor Inspector Strings 1 Answer

Assigning multiple assets to multiple variables on inspector 1 Answer

Lighting disappears when switching scenes 0 Answers

Axis lines on Canvas 0 Answers

editor script problem, looping 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