- Home /
Help With Enemy Health bars
Ok. So here is my problem: I am trying to make enemy healthbars for my enemies. This shouldn't be too hard to just add a guitexture above individual enemies and display their healthbars on it, however, my enemies are all instantiated and so i can't find a way to overcome the problem of each instantiated enemy having its own health bar.
I have looked at the following link "ObjectLabel.js" and despite the fact that the code is supposed to be used for gui texts rather than an image, my final code will probably be similar to it. Something important I know is that im going to need to use an ONGUI(){} function somewhere, because Unity doesn't allow you to make any GUI texture or text as a child of a prefab in the inspector.
To make it simpler for anyone wanting to help me with coding this, I am not going to clamp the enemies' healthbars to the screen (They won't be visible once an enemy leaves the screen).
It would also be cool if I could know whether or not the healthbars for the enemy needs to be attached to the enemy prefab or to the script which instantiates them (or even a bit in both!).
AND ALSO!!!, Is there any other approach that would save processing or is this the fastest method; because in the final stages of the game there may be up to 30 enemies on the screen at once.
Thanks in advance = )
Answer by Professor Snake · Feb 20, 2013 at 01:18 PM
Using OnGUI would not be advised for such a task. Instead, have two planes, a red and a green one, that represent each enemy's life bar. Have them be a child of an empty gameobject and attach that to the enemy's prefab. Then you can modify the green plane's x size based on the enemies' health. For instance:
var initialGreenLength:float;
var greenBar:GameObject;
var health:float=100;
var maxHealth:float=100;
function Awake(){
health=maxHealth;
initialGreenLength=.greenBar.transform.localScale.x;
}
function Update(){
greenBar.transform.localScale.x=initialGreenLength*(health/maxHealth);
}
In order to have the planes always face the camera, you can use this simple piece of code somewhere:
transform.rotation=camera.main.transform.rotation;
In order to make it simple, have the above code edit the rotation of the parent empty gameobject of the two bars. This is what the two bars should look like after some damage has been applied (Yes, cubes work equally as well): You can also use another line to move the green cube to the side, in order to have a more traditional life bar. I am experimenting with the values it needs at the moment, i'll post the code for that once i properly figure it out. Make sure to avoid Z-Fighting on the front by placing them properly.
Thanks Snake,
I'll use this method for the healthbars. I haven't used the code yet, but as long as i dont add any colliders to the bar, it shouldn't be counted as part of the enemy which can be damaged right?
Thanks Prof Snake!. THe health bars look amazing. HOWEVER, there is a new problem that arises because of this: All the health bars have the same variable. I cant do them individually due to the fact that all the enemies are instantiated. Is there a way i can make the health bars not be all decreased when i attack one..
Each healthbar should be part of each enemy's prefab. They should be instantiated along with the enemies.
Thanks for the answer, Snake, it makes my game look 100x better and with some simple code, i added on like a value so it shows how much health remaining out of 100.
Answer by Spherical Cow · Jun 11, 2013 at 01:49 PM
Below is a minimally altered version of Professor Snake's code, converted to c#, with an added section that "uncenters" the health bar and makes it appear to negate from the right hand side (a traditional floating health bar). It works perfectly in my project, so I hope it helps out!
using UnityEngine;
using System.Collections;
/// <summary>
///
/// Created by A.Roberts, June 9, 2013
///
/// Attach to empty gameObject that is parent to both the green
/// and red planes. Drag green bar into the "greenBar" public
/// field.
///
/// </summary>
public class EnemyHealthBar_Green: MonoBehaviour {
public float initialGreenLength;
public GameObject greenBar;
public float curHealth;
public float maxHealth;
public float lastHealth;
Vector3 greenPos;
EnemyHealth healthScript;
public float timer;
float time = 2;
void Awake ()
{
//loads enemy health value from healthScript
healthScript = transform.parent.gameObject.GetComponent<EnemyHealth>();
curHealth = healthScript.curHealth;
maxHealth = healthScript.maxHealth;
//stores two health values, will come in later
lastHealth = curHealth;
}
void Update ()
{
timer -= Time.deltaTime;
if(timer <= 0)
{
timer = 0.05f;
// adjusts the greenHealthBar so that as the enemy takes damage
// the bar shifts to the left, making it appear that the damage
// is coming off the right side of the bar and not equally from
// each end.
if(lastHealth > curHealth)
{
greenPos = greenBar.transform.localPosition;
greenPos.x = (lastHealth - curHealth)/curHealth;
greenBar.transform.localPosition = greenPos;
lastHealth = curHealth;
}
}
curHealth = healthScript.curHealth;
maxHealth = healthScript.maxHealth;
// C# conversion of Professor Snake's awesome code from Unity forum's
// http://answers.unity3d.com/questions/403008/help-with-enemy-health-bars.html
Vector3 greenScale = greenBar.transform.localScale;
greenScale.x = 2 * (curHealth/maxHealth);
greenScale.y = greenScale.y;
transform.localScale = greenScale;
//keeps bar facing camera
transform.LookAt(Camera.main.transform);
}
}
I do use javascript for my stuff but thumbs up, cause now other people who use C# can now use this.
i cant seem to get this code to work, was there some edit or something that was not posted ?
No edits to scripts, but there is more going on behind it.
Hierarchy setup.
Enemy (with EnemyHealth script)
GreenBar (<empty gameObject> with EnemyHealthBar_Green script)
Green Bar texture (png/bmp/jpeg what have you)
RedBar (<empty gameObject> with EnemyHealthBar_Red script)
Red Bar texture (png/bmp/jpeg what have you)
(edited above script with current version, commenting in other scripts below)
using UnityEngine;
using System.Collections;
public class EnemyHealth : $$anonymous$$onoBehaviour {
public float maxHealth = 100;
public float curHealth = 100;
public Transform ticketPrefab;
public float healthBarLength;
// bool showHealthBar;
public GameObject greenBar;
public GameObject redBar;
void Start()
{
healthBarLength = Screen.width /2;
showHealthBar = false;
}
// void OnTriggerEnter(Collider other)
// {
// if(other.collider.tag == "Player")
// {
// showHealthBar = true;}
// }
// void OnTriggerExit(Collider other)
// {
// if(other.collider.tag == "Player")
// {
// showHealthBar = false;}
// }
public void AdjustCurrentHealth(int adj)
{
curHealth += adj;
if(curHealth < 0)
curHealth = 0;
if(curHealth == 0)
{
Destroy(gameObject);
Instantiate(ticketPrefab, transform.position, transform.rotation);
}
if(curHealth > maxHealth)
curHealth = maxHealth;
if(maxHealth < 1)
maxHealth = 1;
healthBarLength = (Screen.width / 2) * (curHealth / (float)maxHealth);
}
void Update()
{
AdjustCurrentHealth(0);
if(showHealthBar)
{
greenBar.renderer.enabled = true;
redBar.renderer.enabled = true;
}
else
{
greenBar.renderer.enabled = false;
redBar.renderer.enabled = false;
}
}
}
using UnityEngine;
using System.Collections;
public class EnemyHealthBar_Red : $$anonymous$$onoBehaviour {
public GameObject RedBar;
public float curHealth;
public float maxHealth;
Transform Player;
EnemyHealth healthScript;
void Awake ()
{
healthScript = transform.parent.gameObject.GetComponent<EnemyHealth>();
curHealth = healthScript.curHealth;
maxHealth = healthScript.maxHealth;
}
void Update ()
{
curHealth = healthScript.curHealth;
maxHealth = healthScript.maxHealth;
Vector3 redScale = RedBar.transform.localScale;
redScale.x = 2 * (maxHealth/maxHealth);
transform.localScale = redScale;
transform.LookAt(Camera.main.transform);
}
}
Answer by Rick.Miranda · Feb 04, 2014 at 03:07 PM
I'm using the following to hang the enemy health bar (GUI Texture) on an empty game object attached to the enemy:
public class GUI_Placement : MonoBehaviour
{
public Transform target; //The target is set as the empty object attached to the enemy from the inspector
void Update ()
{
transform.position = Camera.main.WorldToViewportPoint(target.position);
//transform.rotation = Camera.main.transform.rotation; //
}
}
This works well in placing the GUI Texture (health bar) in the vicinity of the enemy. But there's a problem I'm trying to resolve. This is a top down game where the enemy moves in 2 dimensions. As the enemy starts the move around, the health bar stays at a fixed point relative to the enemy but will also rotate around so that the bar is always horizontal with the screen. What I want is the bar to keep the same orientation that the enemy has. The enemy is a vehicle so I want the bar to stay perpendicular to the enemy's local forward vector at all times. Any advice on how to do this will be great.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Issue with GUITexture width. 1 Answer
GUI.Button not responding when drawn in a Rect. 2 Answers
Texture's Alpha is not Transparent when I use it as a GUI.label 1 Answer
How do I make a custom health bar? 0 Answers