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 Register callback for after a bound property has been updated

Discussion in 'UI Toolkit' started by RobO_HB, Aug 4, 2023.

  1. RobO_HB

    RobO_HB

    Joined:
    Sep 16, 2013
    Posts:
    16
    I have a situation that is proving somewhat tricky, and I'm wondering if I'm missing some relatively easy way to handle this.

    There is a particular ScriptableObject subclass for which we have a custom inspector. In addition, there is a custom window that has an InspectorElement which shows said custom inspector for a particular ScriptableObject (and that custom window also has other things that are useful to see/manipulate at the same time).

    The custom inspector has fields (EnumFields, etc.) bound using the Binding Path that can be specified in the UI Builder. When one of these fields changes, the value in the underlying ScriptableObject changes. In isolation there are no problems there.

    Where I'm running into an issue is in the custom window with the inspector element. I want the ability to receive some sort of a callback when one of the fields of the ScriptableObject has changed, so then I can update other things in the window that are not part of the ScriptableObject's inspector. The issue that I'm having is, if I use RegisterCallback() with a ChangeEvent for any given field, the window's callback is getting called *before* the binding for that field. In other words, the ScriptableObject has not yet been updated when the window's ChangeEvent callback is called.

    I could take the newValue in the ChangeEvent parameter, but that means splitting the window update into several different pieces that update independently depending on exactly what changed. I already have a method that takes an object of the ScriptableObject's type and refreshes the whole window accordingly, so I'd really like to make use of that. But the order of operations is proving difficult.

    Is there a way to register for a callback that says "This bound value has changed (and is now updated to the new value)"? Or, even better, is there a callback for when a ScriptableObject has been changed, so I can refresh the window once that has happened?
     
  2. _geo__

    _geo__

    Joined:
    Feb 26, 2014
    Posts:
    1,111
    Not sure I followed 100% but could you not update the SO with the value from the parameter manually and then trigger the redraw? So no matter which comes first the SO is always up-to-date. The window would be redrawn twice, but the second time it would be coming from the registered change event with all data set accordingly. Bit of a waste but maybe a workaround.
     
  3. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    700
    Granted that you modify your value in a setter then just invoke an event (regular or UnityEvent) from there and any script that is listening will be notified.
     
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,769
  5. oscarAbraham

    oscarAbraham

    Joined:
    Jan 7, 2013
    Posts:
    431
    Hi. I'm not sure I understand completely your case. If you share some code and images, I may be able to offer some ideas that could solve your problems better. That said, there's certainly ways to do exactly what you are asking at the end of your post:

    Yes! Use the TrackPropertyValue extension method.

    Yes! Use the TrackSerializedObjectValue extension method. I haven't tested it with the most recent Unity versions, but, at least in the past, it had some problems with SerializeReference fields, especially when those fields created circular references. Just be aware of that.

    I'd suggest using these extension methods with an element that's replaced every time you change which ScriptableObject is being inspected in your Window, as the only way to stop tracking a property or an object is to remove the VisualElement that's tracking them.
     
    spiney199 likes this.