Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
2 captures
13 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
0
Question by PlayCreatively · Oct 19, 2020 at 06:42 PM · editorinspectorpropertydrawerfieldproperty

How to assign a field within a PropertyDrawer?

Is it possible to access field variables and edit inside of a PropertyDrawer or is it just for properties?

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

Answer by SolidAlloy · Oct 19, 2020 at 09:12 PM

Perhaps, it is the bad naming, but the "Property" part in PropertyDrawer does not mean it is for properties. In fact, it is the opposite - PropertyDrawers are for serialized fields: private fields marked with the [SerializeField] attribute and public fields. PropertyDrawer cannot be used for a property because properties are not serialized by Unity.

PropertyDrawers are used to customize the look of serialized fields in the inspector. For each serialized field, Unity creates a SerializedProperty object (not to confuse with C# property). When you implement a PropertyDrawer class, Unity provides you with the SerializedProperty object, so that you can access the field value and draw the field yourself.

Why would we need SerializedProperty if we could access and change the field value directly? When you change the field value, it does not get automatically serialized (saved to a text file). You would need to save a new value to the asset each time it is changed. However, SerializedProperty does it for you. You just describe how you want the field to be displayed, and SerializedProperty takes care of the serialization part.

I tried to create a simple yet meaningful example of how you can implement a custom PropertyDrawer. Let's say we have a Player MonoBehaviour that contains a PlayerHealth field:

 public class Player : MonoBehaviour
 {
     [SerializeField] private PlayerHealth _health;
 }
 
 [Serializable]
 public class PlayerHealth
 {
     public int MaxHealth = 100;
     public int CurrentHealth = 100;
 }


You don't want users to assign a current health value higher than the max health. You can create a slider with [Range(0, 100)] but max health can be changed too. Then, it would be natural to create PropertyDrawer like this:

 [CustomPropertyDrawer(typeof(PlayerHealth))]
 public class PlayerHealthDrawer : PropertyDrawer
 {
     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
     {
         EditorGUI.BeginProperty(position, label, property);
 
         // Draw the MaxHealth field.
         SerializedProperty maxHealthProperty = property.FindPropertyRelative(nameof(PlayerHealth.MaxHealth));
         EditorGUILayout.DelayedIntField(maxHealthProperty);
 
         SerializedProperty currentHealthProperty = property.FindPropertyRelative(nameof(PlayerHealth.CurrentHealth));
 
         // If the MaxHealth value was changed, check that CurrentHealth is not higher.
         if (currentHealthProperty.intValue > maxHealthProperty.intValue)
             currentHealthProperty.intValue = maxHealthProperty.intValue;
 
         // Draw the CurrentHealth field as a slider, where max value is MaxHealth.
         EditorGUILayout.IntSlider(currentHealthProperty, 0, maxHealthProperty.intValue);
 
         EditorGUI.EndProperty();
     }
 }


And now you have a slider field with a variable max value: alt text


showcase.gif (202.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 SolidAlloy · Oct 20, 2020 at 05:29 AM 1
Share

I noticed I didn't answer your question directly. How can you assign a value to a field? First, you need to find the field by its name. If the field is public, I recommend you use nameof(ClassName.FieldName) as I did above. When the SerializedProperty bound to the field is found, you can assign a value to the field via SerializedProperty.intValue (or boolValue, or other [name]Value; SerializedProperty has a bunch of these). However, most of the times, you don't have to do this. You just draw the field (e.g. EditorGUILayout.DelayedIntField(maxHealthProperty)), and when you change the value in the inspector, it will automatically change in the class field.

avatar image PlayCreatively SolidAlloy · Oct 20, 2020 at 06:03 AM 0
Share

But what if the field I'm trying to access and edit is a delegate or custom class object?

avatar image SolidAlloy PlayCreatively · Oct 20, 2020 at 08:06 PM 0
Share

Custom class object

Such a class needs to have the Serializable attribute. You can leave it up to Unity to draw the class in the inspector. It will just draw its fields in a foldout like it would for $$anonymous$$onoBehaviour fields.

 public class TestBehaviour : $$anonymous$$onoBehaviour
 {
     [SerializeField] private SerializableParent _parentClass;
 }
 
 [Serializable]
 public class SerializableParent
 {
     [SerializeField] private SerializableChild _childClass;
 }
 
 [Serializable]
 public class SerializableChild
 {
     [SerializeField] private string _firstField;
     [SerializeField] private int _secondField;
 }
 
 [CustomPropertyDrawer(typeof(SerializableParent))]
 public class SerializableParentDrawer : PropertyDrawer
 {
     EditorGUI.BeginProperty(position, label, property);
 
     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
     {
         SerializedProperty serializableChild = property.FindPropertyRelative(nameof("_childClass");
         EditorGUILayout.PropertyField(serializableChild); // This will just render a foldout with a string field and an int field.
     }
 
     EditorGUI.EndProperty();
 }


If you need to access/customize the SerializableChild fields, you can access them by path:

 SerializedProperty firstField = property.FindPropertyRelative("_childClass._firstField");
 // Draw firstField or access its value.


If you need to customize the look of SerializableChild, I advise that you create a separate PropertyDrawer for it. Then, when you use EditorGUILayout.PropertyField(serializableChild) in the SerializableParent PropertyDrawer, it will automatically find the custom SerializableChild PropertyDrawer you created earlier and will draw its fields according to that drawer.

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

187 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 avatar image

Related Questions

Custom PropertyDrawer in Array. Problem with expanding. 0 Answers

Customizing Inspector variables. 2 Answers

How do I implement Draggable Properties with custom Labels in Editor or PropertyDrawer? 1 Answer

exclude public field from inspector 2 Answers

How To Draw a PropertyDrawer within a PropertyDrawer 0 Answers


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