- Home /
[C#]Health Regeneration and Delay
So I am trying to make a health regeneration system but I have run into a few problems, the first one being that because time.deltatime is a float, instead of my health regenerating like it should (91-92-93 and so on) it regenerates but there are a ton of decimals (ex. 91.81238%) I was wondering how to fix this problem to have my health only regenerate in whole number increments. The other thing I am trying to do is create a 10 second delay between when the last time my character took damage, till when the regeneration actually starts. Code is below and thank you in advance.
using UnityEngine;
using System.Collections;
public class PlayerHealth : MonoBehaviour {
public int maxHealth = 100;
public float curHealth = 100;
public float regeneration = 5;
public float healthBarLength;
// Use this for initialization
void Start () {
healthBarLength = Screen.width / 2;
}
// Update is called once per frame
void Update () {
AdjustCurrentHealth (0);
if (curHealth < maxHealth)
curHealth += regeneration * Time.deltaTime;;
}
void OnGUI() {
GUI.Box (new Rect (900, 870, healthBarLength, 20), curHealth + "/" + maxHealth);
}
public void AdjustCurrentHealth(int adj) {
curHealth += adj;
if (curHealth < 0)
curHealth = 0;
if (curHealth > maxHealth)
curHealth = maxHealth;
if (maxHealth < 1)
maxHealth = 1;
healthBarLength = (Screen.width / 2) * (curHealth / (float)maxHealth);
}
}
Answer by getyour411 · Apr 18, 2014 at 05:55 AM
I do it like this; you'd have to fill in the blanks and modify to your set up
void Update() {
// If game is paused, don't do any of this
if (QM_Utils.gamePaused)
return;
if(curHealth != maxHealth && !isRegenHealth) {
StartCoroutine(RegainHealthOverTime());
}
}
private IEnumerator RegainHealthOverTime() {
isRegenHealth = true;
while (curHealth < maxHealth) {
AdjustCurrentHealth (1);
CalcHealthPct (curHealth);
yield return new WaitForSeconds (healthRegenRate);
}
isRegenHealth = false;
}
Answer by robertbu · Apr 18, 2014 at 05:50 AM
In Start() put:
InvokeRepeating("Regenerate", 0.0f, 1.0 / regeneration);
Then write the function Regenerate():
void Regenerate() {
if (curHealth < maxHealth)
curHealth += 1.0f;
}
Or if you make curHealth and 'int', you can just do curHealth++.
Now what could I add to only make this execute if I have not taken damage for 10 seconds?
At the top of the file put:
private float timestamp = 0.0;
Then when you take damage do:
timestamp = Time.time;
Then Regenerate() becomes:
void Regenerate() {
if (curHealth < maxHealth && Time.time > (timestamp + 10.0f))
curHealth += 1.0f;
}
Cant seem to get it to work because my health and damage script are two different scripts, right now it waits 10 seconds after I take damage to begin regenerating, but if i take damage again after the initial 10 seconds, it keeps regenerating. Both scripts included below.
public class PlayerHealth : $$anonymous$$onoBehaviour {
public int maxHealth = 100;
public float curHealth = 100;
public int regeneration = 5;
private float timestamp = 0.0f;
public float healthBarLength;
// Use this for initialization
void Start () {
InvokeRepeating("Regenerate", 0.0f, 10.0f / regeneration);
healthBarLength = Screen.width / 2;
}
// Update is called once per frame
void Update () {
AdjustCurrentHealth (0);
}
void OnGUI() {
GUI.Box (new Rect (900, 870, healthBarLength, 20), curHealth + "/" + maxHealth);
}
public void AdjustCurrentHealth(int adj) {
curHealth += adj;
if (curHealth < 0)
curHealth = 0;
if (curHealth > maxHealth)
curHealth = maxHealth;
if (maxHealth < 1)
maxHealth = 1;
healthBarLength = (Screen.width / 2) * (curHealth / (float)maxHealth);
}
void Regenerate() {
if (curHealth < maxHealth && Time.time > (timestamp + 10.0f))
curHealth += 1.0f;
}
}
using UnityEngine;
using System.Collections;
public class EnemyAttack : $$anonymous$$onoBehaviour {
public GameObject target;
public float attackTimer;
public float coolDown;
// Use this for initialization
void Start () {
attackTimer = 0;
coolDown = 2.0f;
}
// Update is called once per frame
void Update () {
if (attackTimer > 0)
attackTimer -= Time.deltaTime;
if (attackTimer < 0)
attackTimer = 0;
if (attackTimer == 0) {
Attack ();
attackTimer = coolDown;
}
}
private void Attack() {
float distance = Vector3.Distance (target.transform.position, transform.position);
Vector3 dir = (target.transform.position - transform.position).normalized;
float direction = Vector3.Dot (dir, transform.forward);
Debug.Log (distance);
if (distance < 3f) {
if (direction > 0) {
PlayerHealth eh = (PlayerHealth)target.GetComponent ("PlayerHealth");
eh.AdjustCurrentHealth (-10);
}
}
}
}
Answer by Sefcio · Jun 23, 2015 at 08:01 PM
This is great, based on what you did I made my part of this script like this:
public class Health : MonoBehaviour {
public int startingHealth = 100;
public int currentHealth;
public int healthReg;
bool isRegenHealth;
void Awake ()
{
currentHealth = startingHealth;
}
void Update()
{
if(currentHealth != startingHealth && !isRegenHealth)
{
StartCoroutine(RegainHealthOverTime());
}
}
private IEnumerator RegainHealthOverTime()
{
isRegenHealth = true;
while (currentHealth < startingHealth)
{
Healthregen ();
yield return new WaitForSeconds (1);
}
isRegenHealth = false;
}
public void Healthregen()
{
currentHealth += healthReg;
}
Your answer
Follow this Question
Related Questions
C# Health regeneration delay after hit 0 Answers
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Why don't my send messages work? 2 Answers
If health = 0, show a GUI.button C# 2 Answers