Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question Smooth healthbar and softly damage

Discussion in 'Scripting' started by Pazo_Games, Apr 2, 2024.

  1. Pazo_Games


    Oct 10, 2023

    This is the code of my health bar. It works but I want it to damage smoothly but it jump. What can I do?
  2. ArachnidAnimal


    Mar 3, 2015
    majyo_arisu likes this.
  3. orionsyndrome


    May 4, 2014
    Instead of instantly affecting the value that is solely responsible for the visual feedback, you lay another layer of logic on top of that. Essentially you decouple the 'ground truth' from the visual feedback and introduce a "driver".

    Now your 'ground truth' isn't what is actually displayed, but instead it's the target value which the visual system uses to 'animate' itself. This way you can modify the style or quality of this animation without touching the 'ground truth'.

    Here's a quick example (just a pseudocode to illustrate)

    Flat update
    Code (csharp):
    1. float health = 100f;
    3. void Update() {
    4.   updateShownValue(health);
    5. }
    7. void ModifyHealth(float modifier) {
    8.   health = Mathf.Clamp(health + modifier, 0f, 100f);
    9. }
    Animated update
    Code (csharp):
    1. float health = 100f;
    2. float display = 0f;
    4. void Update() {
    5.   var changed = change(ref display, towards: health, rate: 10f);
    6.   if(changed) updateShownValue(display);
    7. }
    9. void ModifyHealth(float modifier) {
    10.   health = Mathf.Clamp(health + modifier, 0f, 100f);
    11. }
    where this helper function could be defined as
    Code (csharp):
    1. bool change(ref float value, float towards, float rate) {
    2.   const float E = 1E-6f; // how small is too small of a difference
    3.   var d = towards - value; // get the difference (this will have a sign)
    4.   var ad = Mathf.Abs(d); // remove the sign
    5.   if(ad < E) return false; // if it's near-zero abort
    6.   value += Mathf.Clamp(Mathf.Sign(d) * rate * Time.deltaTime, -ad, ad); // * see edit below
    7.   return true;
    8. }
    Depending on how you standardize your values (and what is your desired approach in style), you can as well use animation easing or animation curves. Or you could use other common functions as described by ArachnidAnimal above.

    The core of the function will sign the rate accordingly and scale it down to your frame time. Then it will clamp it to the actual difference, to prevent overshooting, before applying it to the displayed value.

    From this you can gather that the rate is like speed in this context: it represents how much the value will [visibly] change over 1 second. Make sure it's strictly a positive number (I didn't want to handle this for clarity).

    fixed a typo

    changed ApplyDamage to ModifyHealth
    Last edited: Apr 2, 2024