0

I want to do a dropdown menu that works similar to the tag system but for my sound names. However, whenever I have my custom properties in a container and I change one of them, every other property also changes.

This is my property drawer code:

using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(SoundName))]
public class SoundNamePropertyDrawer : PropertyDrawer
{
    SoundNamesContainer _soundNamesContainer;
    SerializedProperty _nameProperty;
    SerializedProperty _indexProperty;

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        if(_nameProperty == null)
        {
            _nameProperty = property.FindPropertyRelative("Name");
            _indexProperty = property.FindPropertyRelative("index");
        }
        if(_soundNamesContainer == null)
            _soundNamesContainer = Resources.Load("SoundNames") as SoundNamesContainer;

        EditorGUI.BeginProperty(position, label, property);
        _indexProperty.intValue = EditorGUI.Popup(position, _indexProperty.intValue, _soundNamesContainer.Names);
        _nameProperty.stringValue = _soundNamesContainer.Names[_indexProperty.intValue];
        
        EditorGUI.EndProperty();
    }

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

3
  • Not enough info. The code looks fine, textbook even. I only see two properties and it looks like you do find them and change both according to the dropdown choice. Do you mean that there are more properties in the SerializedProperty you are messing with that also get affected? If so, it's not this drawer but some other part of your code reacting to the changes in the 2 properties above. Commented Sep 10, 2024 at 22:17
  • @NPatch there is indeed an issue as the same drawer instance is used for all items of a collection - see below ;) Commented Sep 11, 2024 at 18:55
  • @derHugo You're right. I didn't read this properly and didn't understand that this drawer would be used in multiple instances. Assumed the Name/Index combo was a one instance thing so I didn't think much of the if == null. Commented Sep 12, 2024 at 10:27

1 Answer 1

3

For arrays/lists the same instance of the drawer is used for all items!

So instead of

if(_nameProperty == null)
{
    _nameProperty = property.FindPropertyRelative("Name");
    _indexProperty = property.FindPropertyRelative("index");
}

you should just use

_nameProperty = property.FindPropertyRelative("Name");
_indexProperty = property.FindPropertyRelative("index");

otherwise you will always use the cached first item property for the entire collection.

The performance overhead for getting the properties repeatedly should actually be quite neglectable ;)

I wouldn't even store them in a class field since the same kind of issues could then occurre if you begin to use the properties also within GetPropertyHeight.

It makes sense in an Editor but within a PropertyDrawer (imho) it's always best to just get and store the properties within the methods where needed.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.