Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Dropdown Attribute does not trigger OnValidate

Discussion in 'Scripting' started by Balphagore, Sep 24, 2023.

  1. Balphagore

    Balphagore

    Joined:
    Jul 18, 2019
    Posts:
    81
    I'm using a small asset from the unity asset store:
    https://assetstore.unity.com/packages/tools/utilities/dropdown-attribute-180951

    In general, it works as expected, but it does not trigger OnValidate when the field where it is placed changes.


    Code (CSharp):
    1. [CreateAssetMenu(fileName = "Types")]
    2. public class Types : ScriptableObject
    3. {
    4.     public List<string> TypeNames;
    5. }

    Code (CSharp):
    1. [CreateAssetMenu (fileName = "Data")]
    2. public class Data : ScriptableObject
    3. {
    4.     [SerializeField]
    5.     private Types _types;
    6.     [Dropdown("_types.TypeNames")]
    7.     public string Type;
    8.  
    9.     private void OnValidate()
    10.     {
    11.         Debug.Log(Type);
    12.     }
    13. }
    The Dropdown Attribute itself is inherited from PropertyAttribute and has a CustomPropertyDrawer

    How can I make some logic work in an object if a field marked with Dropdown Attribute changes?
     

    Attached Files:

  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    4,063
    I'm guessing it uses reflection to change the field and thus it won't trigger OnValidate. You could add that to the script though: if the value did change just call OnValidate manually on the target script.
     
  3. Balphagore

    Balphagore

    Joined:
    Jul 18, 2019
    Posts:
    81
    I don't really need OnValidate, I just wanted to run additional logic when the value changes. But the value changes so that even OnValidate is not called.

    In the attribute itself, I found only constructors and they are triggered only when a window opens with a field marked with this attribute.

    Code (CSharp):
    1. public class DropdownAttribute : PropertyAttribute
    2. {
    3.     public Type Type = null;
    4.     public string ListPath = "";
    5.     public string ItemNameProperty = "";
    6.     public List<Object> List = new List<Object>();
    7.     public int SelectedID = -1;
    8.     public GetItemNameCallback GetItemName = null;
    9.     public DropdownAttribute(string listPath, string ItemNameProperty)
    10.     {//With property name to get name
    11.         //[Dropdown("SkillDatabase.Instance.SkillList", "skillID")]
    12.         ListPath = listPath;
    13.         GetItemName = ( (baseMaster, obj) =>
    14.          {
    15.              return ReflectionSystem.GetValue(baseMaster, obj, ItemNameProperty)?.ToString();
    16.          });
    17.         this.ItemNameProperty = ItemNameProperty;
    18.     }
    19.     public DropdownAttribute(string listPath)
    20.     {
    21.         ListPath = listPath;
    22.         GetItemName = ((baseMaster, master) =>
    23.         {
    24.             if(master is Object)
    25.             {//is Unity Object
    26.                 return master.GetType().GetProperty("name").GetValue(master).ToString();
    27.             }
    28.             else if(master is string)
    29.             {//string
    30.                 return master.ToString();
    31.             }
    32.             else if(master.GetType().IsPrimitive)
    33.             {//short, long, int, bool, char, double, float
    34.                 return master.ToString();
    35.             }
    36.             else
    37.             {//object
    38.                 return JsonUtility.ToJson(master);
    39.             }
    40.         });
    41.     }
    42. }
    PropertyDrawer is very large and I didn’t really understand it.

    How do I call some logic on the target ScriptableObject when the value of a field with this attribute changes? Should I search in PropertyDrawer?