I am very new to coding and am working on my first health bar. I followed everything on the tutorial and it worked!!! Unfortunately, when i went to the next video where he added text to the bar it showed these 2 errors. I have no clue what they mean and how to fix them because I thought I did everything right. Sorry if it’s a lot of code, I just didn’t want to miss anything. By the way I’m using TextMeshPro… Thanks!!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class PlayerHealth : MonoBehaviour
{
private float health;
private float lerpTimer;
public float maxHealth = 100f;
public float chipSpeed = 2f;
public Image frontHealthBar;
public Image backHealthBar;
[SerializeField]
private TextMeshProUGUI healthAmmount;
// Start is called before the first frame update
void Start()
{
health = maxHealth;
}
// Update is called once per frame
void Update()
{
health = Mathf.Clamp(health, 0, maxHealth);
UpdateHealthUI();
if (Input.GetKeyDown(KeyCode.X))
{
TakeDamage(Random.Range(5, 10));
}
if (Input.GetKeyDown(KeyCode.Z))
{
RestoreHealth(Random.Range(5, 10));
}
}
public void UpdateHealthUI()
{
Debug.Log(health);
float fillF = frontHealthBar.fillAmount;
float fillB = backHealthBar.fillAmount;
float hFraction = health / maxHealth;
if (fillB > hFraction)
{
frontHealthBar.fillAmount = hFraction;
backHealthBar.color = Color.red;
lerpTimer += Time.deltaTime;
float percentComplete = lerpTimer / chipSpeed;
backHealthBar.fillAmount = Mathf.Lerp(fillB, hFraction, percentComplete);
}
if (fillF < hFraction)
{
backHealthBar.fillAmount = hFraction;
backHealthBar.color = Color.green;
lerpTimer += Time.deltaTime;
float percentComplete = lerpTimer / chipSpeed;
frontHealthBar.fillAmount = Mathf.Lerp(fillF, hFraction, percentComplete);
}
//healthAmmount.text = Mathf.Round(health) + "/" + Mathf.Round(maxHealth);
public void TakeDamage(float damage)
{
health -= damage;
lerpTimer = 0f;
}
public void RestoreHealth(float healAmount)
{
health += healAmount;
lerpTimer = 0f;
}
}
}
Please post the line numbers the errors are on. When you highlight an error in the console it will show you what line number it’s on, which helps with the debugging process. Perhaps once you see the line numbers you’ll be able to fix it without any help.
Even more important, we are humans, not compilers. We don’t care or remember error codes. The compiler already gives you an english description of the error. So when you ask questions about an actual error you got, include the actual error and not just the error code. The error would be something like
Your mistake is that you put your two methods TakeDamage and RestoreHealth INSIDE your “UpdateHealthUI” method. In the past you would have gotten a different error because local methods weren’t a thing. Nowadays C# supports local methods. However local methods can not have an access modifier since they can only be used inside the method they are defined in. You most likely don’t want local methods but you want them inside the class.
2 Likes
It also makes no sense to make a health limit and update its UI interface inside the Update method. Put the logic in a separate method and call it automatically ONLY when health changes.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class PlayerHealth : MonoBehaviour
{
private float health;
private float lerpTimer;
public float maxHealth = 100f;
public float chipSpeed = 2f;
public Image frontHealthBar;
public Image backHealthBar;
[SerializeField]
private TextMeshProUGUI healthAmmount;
// Start is called before the first frame update
void Start()
{
health = maxHealth;
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.X))
{
TakeDamage(Random.Range(5, 10));
}
if (Input.GetKeyDown(KeyCode.Z))
{
RestoreHealth(Random.Range(5, 10));
}
}
void UpdateHealthUI()
{
Debug.Log(health);
float fillF = frontHealthBar.fillAmount;
float fillB = backHealthBar.fillAmount;
float hFraction = health / maxHealth;
if (fillB > hFraction)
{
frontHealthBar.fillAmount = hFraction;
backHealthBar.color = Color.red;
lerpTimer += Time.deltaTime;
float percentComplete = lerpTimer / chipSpeed;
backHealthBar.fillAmount = Mathf.Lerp(fillB, hFraction, percentComplete);
}
if (fillF < hFraction)
{
backHealthBar.fillAmount = hFraction;
backHealthBar.color = Color.green;
lerpTimer += Time.deltaTime;
float percentComplete = lerpTimer / chipSpeed;
frontHealthBar.fillAmount = Mathf.Lerp(fillF, hFraction, percentComplete);
}
//healthAmmount.text = Mathf.Round(health) + "/" + Mathf.Round(maxHealth);
}
public void TakeDamage(float damage)
{
health -= damage;
UpdateHealthStuff();
}
public void RestoreHealth(float healAmount)
{
health += healAmount;
UpdateHealthStuff();
}
private void UpdateHealthStuff()
{
health = Mathf.Clamp(health, 0, maxHealth);
lerpTimer = 0f;
UpdateHealthUI();
}
}
Well, not really as he is triggering a lerp towards the actual value when the health changes. The lerp has to happen every frame. He uses Time.deltaTime inside UpdateHealthUI. So calling it once wouldn’t make much sense. I do understand your way of thinking and it’s usually correct. However the animation he aims for would not work this way. He could use coroutines to pull off the animation, however this gives you tons of potential issues when you have overlapping behaviour. So having the animation in Update is one of the simplest solutions.
Instead of those two Lerps, it would be simpler to use a MoveTowards call instead to do the animation.
You’re right, I didn’t even notice the animation inside the UpdateHealthUI method…! Thanks for the correction.
Thanks for all of your help!! It works now!!!