Code check: Using action<float> to update Slider bars. Am I doing it right?

Hello! My first ever question here!

I am building this code myself and was wondering if I am doing it right? I want to make the UI sliders work by doing action < float>. I have two scripts, UI and Movement.

For example, I have my car and its movement is coded in a movement script. Now I implement a fuel function, where the fuel is reduced when I drive the car.
Then I create a UI canvas and add a fuel gauge ie. slider bar for car fuel. I reference this in a UI script. I’m not actually making a car game though. :blush:

Now my idea is, instead of referencing UI script in Movement script to update slider bar, I just make it work with Actions.

Just asking this because I want to know if this is a good practice or if there’s a better solution/alternative for this.

My code example:

public class CarFuelExample : MonoBehaviour
{
    public static Action<float> onFuelValueChanged;
    private float fuelValue;

    public void DecreaseFuel(float value)
    {
        fuelValue -= value;
        onFuelValueChanged(fuelValue);
    }
}

Then, here’s UI code:

public class UIExample : MonoBehaviour
{
    [SerializeField] private Slider fuelSlider;

    public void UpdateSlider(float value)
    {
        fuelSlider.value = value;
    }

    public void OnEnable()
    {
        CarFuelExample.onFuelValueChanged += UpdateSlider;
    }

    public void OnDisable()
    {
        CarFuelExample.onFuelValueChanged -= UpdateSlider;
    }
}

Personally I use UnityEvent.
Use it almost exactly as you have done with actions, but it appears in the Editor, so you can bind components there instead of doing it in the code.

Also - don’t use static in this instance . If you share the class between multiple cars they share the member variable. If you need to access it from the UI, give the UI a specific car in the editor or via code.

Overall, using delegates/events for updating values like that is a great practice. Just don’t do static, as mentioned bu ATate. Also, check for null delegate. Instead of onFuelValueChanged(fuelValue);, do onFuelValueChanged?.Invoke(fuelValue);

I even have a class that wraps an event and the value in a single object, with a special access object that only lets you read it but not set the value (if you want to only do that internally).

( I guess more appropriate name would be “Observable”, a pattern used in reactive programming )