Quick answer: Implement INotifyBindablePropertyChanged. Match binding-path to a public property. Fire propertyChanged from setters.
Health bar bound via UXML. Health field decreases. UI doesn’t. Binding has no signal that the source value changed.
The Symptom
Initial value displays correctly. Subsequent updates don’t reflect. Inspector edits propagate (because of SerializedObject); runtime changes don’t.
The Fix
public class PlayerVM : INotifyBindablePropertyChanged {
int _hp;
[CreateProperty]
public int Health {
get => _hp;
set {
if (_hp == value) return;
_hp = value;
propertyChanged?.Invoke(this,
new BindablePropertyChangedEventArgs(nameof(Health)));
}
}
public event EventHandler<BindablePropertyChangedEventArgs> propertyChanged;
}
UXML side:
<ProgressBar binding-path="Health" low-value="0" high-value="100"/>
Bind once at runtime:
root.dataSource = playerVM;
root.SetBinding("value", new DataBinding { dataSourcePath = new("Health") });
Now playerVM.Health-- updates the bar without manual repaint calls.
SerializedObject Path
For inspector data: rootVisualElement.Bind(serializedObject). Then bindings auto-poll. Outside of Editor, use the runtime data binding API above.
Verifying
Decrement Health from script. Bar shrinks immediately. Console-log propertyChanged firing per setter call.
“Notify on set. Path matches. UI listens.”
Related Issues
For Cinemachine impulse, see impulse. For input system composite, see composite.
Notify on set. UI follows.