0

Here is a basic script for a health system that I will be using in my game. So far the health decrease & increase is triggered using keypresses, but later on with colliders. I was wondering how I can rewrite the script so that when the player losses health, a time delay must happen before losing more health. This is to prevent quickly draining the player's health.

Health Script:

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Health: MonoBehaviour {
    public int health;
    public int numOfHearts;

    public Image[] hearts;
    public Sprite fullHeart;
    public Sprite emptyHeart;

    void Update() {
        if (health > numOfHearts) {
            health = numOfHearts;
        }
        
        for (int i = 0; i < hearts.Length; i++) {

            if (i < health) {
                hearts[i].sprite = fullHeart;
            } else {
                hearts[i].sprite = emptyHeart;
            }

            if (i < numOfHearts) {
                hearts[i].enabled = true;
            } else {
                hearts[i].enabled = false;
            }
        }

        if (Input.GetKeyDown(KeyCode.O)) {
            TakeDamage(1);
        }

        if (Input.GetKeyDown(KeyCode.P)) {
            GainHealth(1);
        }
    }

    void TakeDamage(int damage) {
        health -= damage;
    }

    void GainHealth(int gain) {
        health += gain;
    }
}
karel
  • 5,489
  • 46
  • 45
  • 50
Wymlock
  • 1
  • 1
  • @derHugo your link has nothing to do with his question -- those answers are about waiting to do something in the future -- this question is about not doing something for a while. Why close this question with a bad link? – Hogan Mar 02 '21 at 19:00
  • @Hogan because it is basically exactly the solution for these kind of questions in Unity: Delay the re-allowing of again execute something. It is basically what you are doing in your answer. Note though that your answer is very bad and should not be used as it is because it is absolutely frame-rate dependent .. if you look into the links you will see people answered with such a timer **but** using a float time which is frame-rate independent. This is definitely something that was answered a lot of times .. the first link was just the first I found and provides the most options for delays – derHugo Mar 02 '21 at 19:13
  • @derHugo -- sure mine is bad. But the link you posted does something different. – Hogan Mar 02 '21 at 19:16
  • @Hogan again: it was just the first one and it provides the most options for delaying code execution in Unity. Going from there to put it into an endless loop is OP's homework. See the other three links if the first one doesn't match in your opinion. It is still a duplicate ;) – derHugo Mar 02 '21 at 19:18
  • Wymlock -- here is the answer that addresses your actual problem. https://stackoverflow.com/a/33930663/215752 – Hogan Mar 02 '21 at 19:19
  • @derHugo -- sure I get you -- I just think that it would be hard to see how they are different to a new programmer -- I edited my question to try and make it clearer -- hopefully the OP will get it. – Hogan Mar 02 '21 at 19:22

1 Answers1

-1

The solution below shows how to do it but because it counts in the updates it is frame rate dependent.

Here is an answer that uses timestamps instead of counting "ticks" https://stackoverflow.com/a/33930663/215752

If you don't understand that link take a look at my code and how it "works" should be clearer.


My code here does not take damage unless a certain time has passed... Andrey's solution will slowly update the display to actual value.

add to main object

static cooloff = 0;

also add to main update:

if (cooloff > 0) cooloff--;

then update take damage like so

void TakeDamage(int damage)
{
    const cooloffwait = 100; -- change this value to number of ticks needed

    if (cooloff == 0)
    {
       health -= damage;
       cooloff = colloffwait;
    }
}
Hogan
  • 69,564
  • 10
  • 76
  • 117
  • This is frame-rate dependent and should not be sued like this. If something rather use a `float` timer based on the `Time.deltaTime`, the time passed since last frame ... – derHugo Mar 02 '21 at 19:15
  • Note that also `DateTime` is not a very good solution. `DateTime.Now` is quite expensive and unnecessary. Compare a `float` timestamp to `Time.time` would already be more efficient. But as said probably the best way would be something like [these](https://stackoverflow.com/questions/32070533/is-there-a-better-way-to-reset-cooldown-on-unity) – derHugo Mar 02 '21 at 19:48