Does anyone know how to make the healthbar stop at zero? (it currently goes below zero) Thank you. Code (CSharp): using UnityEngine; using System.Collections; using UnityEngine.UI; public class HealthBar : MonoBehaviour { #region FIELDS // The player's current health public int currentHealth; // The player's max health public int maxHealth; // The health bar's speed public float healthSpeed; // The health text public Text healthText; // The health's image, this is used for color changing public Image visualHealth; // The current xValue of the health private float currentValue; // How often can I take damage public float cooldown; // Indicates if we can take damage or not private bool onCD; // The healthbar's canvas public Canvas canvas; #endregion #region PROPERTIES // Property for accessing the player's health public int Health { get { return currentHealth; } set { currentHealth = value; } } #endregion // Use this for initialization void Start() { // Sets all start values onCD = false; //Sets the current health to the maxHealth currentHealth = maxHealth; } // Update is called once per frame void Update() { HandleHealthbar(); if (Input.GetKeyDown(KeyCode.Space)) { Health -= 10; } } // Handles the healthbar my moving it and changing color private void HandleHealthbar() { // Writes the current health in the text field healthText.text = "Health: " + currentHealth; // Maps the min and max position to the range between 0 and max health currentValue = Map( currentHealth, 0, maxHealth, 0, 1); // Sets the fillAmount of the health to simulate reduction of health visualHealth.fillAmount = Mathf.Lerp( visualHealth.fillAmount, currentValue, Time.deltaTime * healthSpeed ); // If we have more than 50% health we use the green colors if ( currentHealth > maxHealth /2 ) { visualHealth.color = new Color32( ( byte ) Map( currentHealth, maxHealth / 2, maxHealth, 255, 0 ), 255, 0, 255 ); } // If we have less than 50% health we use the red colors else { visualHealth.color = new Color32( 255, ( byte ) Map ( currentHealth, 0, maxHealth / 2, 0, 255 ), 0, 255); } } void OnTriggerStay( Collider other ) { // Used for simulating taking damage if ( other.tag == "Damage" ) { if ( !onCD && currentHealth > 1 ) { // Makes sure that we can't take damage right away StartCoroutine ( CoolDownDmg() ); // Uses the Health Property so that we recolor and rescale the health when we change it Health -= 1; } } // Used for simulating gaining health if ( other.tag == "Health" ) { if ( !onCD && currentHealth < maxHealth ) { // Makes sure that we can't take damage right away StartCoroutine( CoolDownDmg() ); // Uses the Health Property so that we can recolor and rescale the health when we change it Health += 1; } } } // Keeps track of the damage CD IEnumerator CoolDownDmg() { onCD = true; // Waits a while before we are able to take damage again yield return new WaitForSeconds( cooldown ); onCD = false; } // This method maps a range of numbers into another range // <param name="x">The value to evaluate</param> // <param name="in_min">The minimum value of the evaluated variable</param> // <param name="in_max">The maximum value of the evaluated variable</param> // <param name="out_min">The minimum number we want to map to</param> // <param name="out_max">The maximum number we want to map to</param> // <returns></returns> public float Map(float x, float in_min, float in_max, float out_min, float out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } }
Code (CSharp): if (Input.GetKeyDown(KeyCode.Space)) { Health -= 10; if Health < 0 { Health = 0; } } Evry time you decrease the healh check if its less than 0 and if it is set it back to 0
I think this is a classic case of over engineering. I've got several "health" style scripts that work flawlessly with clean code and none of them are this complicated. My general approach is to use a property. Code (CSharp): public int Health { get { return Health; } set { Health = value; if (Health < 0) Health = 0; } } This way you can set Health to anything. You could even add a line in there to make sure it doesn't go over your maxHealth as well. So then you just say Health = 5432948392 and it'll be <maxHealth> or Health = -5839285932 and it will be 0. You could probably use Mathf.Clamp as well, but.. meh. I like the property. I actually cheat and have a call to my "this entity is now dead so clean it up" method inside my if < 0 block. It's considered bad form but it works great in this case.
If you use that code, do not use capital 'H' health inside the property. This will cause the program to crash. Due to infinite looping.
I added: Code (CSharp): if (Health <= 0) { Health = 0; } The health now stops going negative, but there is still one issue: once the currentHealth = 0, the fill keeps cycling (is there a way to stop the fill from continuously going down?) I tried this: Code (CSharp): // Sets the fillAmount of the health to simulate reduction of health if currentHealth !=0 () { visualHealth.fillAmount = Mathf.Lerp( visualHealth.fillAmount, currentValue, Time.deltaTime * healthSpeed ); } The issue is once current health = 0 the fill amount stops in its tracks (ie. does not reach 0 fill since it is going down over time) Anyone know how to fix this?
Just clamp the value after you subtract from it. Mathf.Clamp Also why do you comment everything even when the intent is already obvious based on the names. Commenting the obvious just adds to visual clutter in your code and leads to worse readability. Comments should be about why you did something, not just saying the same thing the code is in different words.
Your teacher needs a lesson in proper coding practise. Comments are to explain intent and reasoning. Not to restate your code. Your code should be largely self documenting, using good variable names and so forth. This guy says it better then me. http://visualstudiomagazine.com/articles/2013/06/01/roc-rocks.aspx?m=1
why even use a If-condition your health can only be between 0 and maxhealth as you have your code right now. So there is no need to update your healthbar only if it is != 0. without the if condition it should therefor work at the 0 point.
Ya aside from documenting my methods and properties, I only comment lines that aren't immediately obvious, or use some obscure logic. For example, using an item number that is counted from 1 to get the next index of the associated list, which is of course counted from 0. When you do something like item = mylist[olditem.IDNumber] it looks like you're trying to get that item, but it's actually 1 beyond. Even if you're familiar with your code at first glance this is counter intuitive. So I'd comment that line to make it clear what is happening.
Code (csharp): public float currentHealth; public float maxHealth; void Update() { if (currentHealth <= 0 || currentHealth >= maxHealth) { currentHealth = (currentHealth <= 0) ? 0 : maxHealth; } } Scale the healthy portion of your healthbar based on currentHealth.
No. There's 2 things wrong with this and arguably 3. 1) You're now comparing values every frame, which could be 30 or 200. Why would you do this instead of just checking when it's needed (property or method that explicitly changes health) ? 2) You're making the comparison twice. You check if health is < 0 and then you check if health is < 0 again. I understand why, but it's not needed. Arguably 3) This is one of those one liners that some people hate. Sure it's cute in its brevity, but it's not clear at a glance. Not a huge deal in and of itself but if the purpose of this suggestion is to advertise a one liner it's not worth it and it's bad practice. I believe that the ? operator should be reserved for default values. It's nice in that you can attempt to set a variable and if for some reason it cannot you can determine what it should default to. Again, #3 is purely my opinion so don't let this rant distract from points #1 and #2 which are the more important. I favor longer files over brevity. I want to be able to read my code like a book. (I know some of you are going to want to say "That's perfectly readable, what are you talking about?" ... I'm talking about my opinion. ) TL;DR -- Don't run logic when you don't have to. With this example you're checking your health values even if the health value hasn't changed since the last check.
Yeah, using the property as you outlined is cheaper. Just throwing some ideas around. I don't use properties enough so it's never in the front of my thoughts to solve stuff like that.
Hope You Can Do It With This Method public class ExampleScript : MonoBehaviour{ Code (CSharp): // This keep Health Between 2 Number So It Dont Go Below Or Grow Up More That it (Sorry For The Bad English) public float Health float Health_Value Health_Value = Mathf.Clamp(Health , Min Number, Max Number) }