Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 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 bonzairob · Jan 11, 2019 at 10:32 PM · arraysenumpropertydrawer

Showing an array with enum as keys in the property inspector

I've got an object where components have individual HP, stored in an array; the array will be accessed via an enum set of the component names. This is a simplified version, there are other things like statuses (on fire, leaking) that each component might have.

 public class Body : MonoBehaviour {

     protected enum COMPONENTS {
         Head,
         Torso,
         LeftArm,
         RightArm,
         LeftLeg,
         RightLeg
     }
     protected static int COMPONENTS_COUNT = 6;


     //maximum HPs for components - visible in editor
     public int[] component_hp_max = new int[COMPONENTS_COUNT];



     //updated current HP for components
     protected int[] component_hp_current = new int[COMPONENTS_COUNT];

      void Start () {
         //for each component...
         for (int i = 0; i < COMPONENTS_COUNT; i++){
             //current hp is the max hp
             component_hp_current[i] = component_hp_max[i];
         }
     }

 }

I want to be able to iterate over the objects, so I think using a dictionary isn't ideal. I'm new to Unity and C#, so perhaps there's a more elegant way.

However, in the property window, the elements get listed like Element 0, Element 1: The Property Editor showing the items named by their index.

Is it possible to use the COMPONENTS enum as the "keys" for the array in the property inspector, so they're listed as Head, Torso, etc.?

(Second question: is there a more elegant way of getting the enum's length than just storing the size in a separate int..?)

screen-shot-2019-01-11-at-222816.png (29.1 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

2 Replies

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

Answer by bonzairob · Jan 12, 2019 at 02:11 PM

I have made a custom PropertyDrawer to accomplish this.

Assets/EnumNamedArrayAttribute.cs

 using UnityEngine;

 public class EnumNamedArrayAttribute : PropertyAttribute
 {
     public string[] names;

     public EnumNamedArrayAttribute(System.Type names_enum_type)
     {
         this.names = System.Enum.GetNames(names_enum_type);
     }
 }

Assets/Editor/DrawerEnumNamedArray.cs

 using UnityEngine;
 using UnityEditor;
 using System.Collections;
 using System.Collections.Generic;

 [CustomPropertyDrawer(typeof(EnumNamedArrayAttribute))]
 public class DrawerEnumNamedArray : PropertyDrawer
 {

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
         EnumNamedArrayAttribute enumNames = attribute as EnumNamedArrayAttribute;

         //propertyPath returns something like component_hp_max.Array.data[4]
         //so get the index from there
         int index = System.Convert.ToInt32(property.propertyPath.Substring(property.propertyPath.IndexOf("[")).Replace("[", "").Replace("]", ""));

         //change the label
         label.text = enumNames.names[index];

         //draw field
         EditorGUI.PropertyField( position, property, label, true );

     }
 }

Usage:

  [EnumNamedArray( typeof(COMPONENTS) )]
  public int[] component_hp_max = new int[COMPONENTS_COUNT];

It's a shame about the typeof() but I couldn't get it to work without it.

alt text


screen-shot-2019-01-12-at-140918.png (50.8 kB)
Comment
Add comment · Show 4 · 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 nights007 · Jul 22, 2020 at 01:36 AM 0
Share

Really simple and great solution, not sure why it doesnt have more upvotes. By the way, i tried this with a struct (with one single float atm) instead of an int and it kinda works out of the box, except theres some overdraw. Any idea how to fix it? Guess height needs to be adjusted for each row..

avatar image idbrii · Nov 30, 2020 at 06:29 PM 0
Share

To prevent errors when adding too many items to the array change line 20:

 if (index < enum_attr.names.Length)
 {
     label.text = enum_attr.names[index];
 }

If we don't assign label, then they keep their default "Element 4" names.

avatar image idbrii idbrii · Jan 06, 2021 at 10:00 PM 0
Share

Also: to support this attribute in a Serializable struct that's inside a list, change IndexOf to LastIndexOf.

Then you should be able to do something like:

 [Serializable]
 public class Health {
   [EnumNamedArray( typeof(CO$$anonymous$$PONENTS) )]
   public int[] component_hp_max = new int[CO$$anonymous$$PONENTS_COUNT];
 }

 [EnumNamedArray( typeof(CO$$anonymous$$PONENTS) )]
 public Health[] component_hp_max = new Health[CO$$anonymous$$PONENTS_COUNT];
avatar image FlyVC · Dec 10, 2020 at 01:28 PM 0
Share

if you have a struct or a class as array elements, expanding them wont work because the required height of the elements wont change.

 public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
     {
         return EditorGUI.GetPropertyHeight(property, label, true);
     }

adding this to DrawerEnumNamedArray.cs, fixed it for me.

avatar image
3

Answer by dan_wipf · Jan 11, 2019 at 10:46 PM

Maybe a different approach of your Question could solve it, if it's a fixed length of array I'd make a new Struct and display this in the Inspector.


like this:


 public class Body : MonoBehaviour {
 
 [System.Serializable] public struct COMPONENTS{
         public int Head;
         public int Torso;
         public int LeftArm;
         public int RightArm;
         public int LeftLeg;
         public int RightLeg;
     }
 
     public COMPONENTS YourNewStruct;
 
 
      
  }



you then call values from COMPONENTS like this:


 int x = YourNewStruct.Head;
 int y = YourNewStruct.LeftLeg;
 
 YourNewStruct.Head = y;
 
 //etc.



result:


Screener of Result


bildschirmfoto-2019-01-11-um-234807.png (25.8 kB)
Comment
Add comment · Show 4 · 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 bonzairob · Jan 11, 2019 at 11:14 PM 0
Share

The trouble is I want to add some other things per-component, like debuffs ("on fire"), or a set of has_died booleans. $$anonymous$$aybe I can work around that though...

avatar image dan_wipf · Jan 12, 2019 at 06:52 AM 0
Share

can you maybe explain what’s the purpose of this code?

avatar image Simon-Larsen · Mar 06 at 08:50 PM 0
Share

This solution was way simplier in my opinion and achieved what I wanted to archieve

avatar image cjsawyer · May 21 at 09:02 PM 0
Share

This was simple and exactly what I needed. For my use case I ended up with a Serializable struct which held several named data objects which were also Serializable structs. This gave me a tidy way to use the inspector define a big set of textures to switch around depending on the setting. I just switch out the data object and update the materials with the new textures. alt text

 // in my class
 public Organizations organizations;
 
 // below my class in the same file
 [Serializable]
 public struct Organizations
 {
     public TextureSet Org1;
     public TextureSet Org2;
     public TextureSet Org3;
 }
 
 [Serializable]
 public struct TextureSet
 {
     public Texture someTexture;
     public Texture otherTexture;
 }
 

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

107 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

Related Questions

Restricting enum options in inspector when using a propertydrawer. 0 Answers

JS: Dump array value in an Enum 1 Answer

Enum to value table/array for editor 1 Answer

PropertyDrawer: Enum to select extended class 0 Answers

alternative for header atrribute for enums 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