Hi! I am having problems making an hp bar. I need the hp bar (which is a plane) to be always facing the player. I tried every billboard script on the wiki and on google and I cant still make it work.
The plane is child of the “monster” gameObject and the camera is child of the “player” gameObject.
Any ideas?
I’ve found one of the neatest ways to do this is to use two cameras… an orthographic ‘GUI’ camera and a scene camera. This is generally not expensive if the camera is only rendering gui components (and you can render the rest of your GUI on it too).
This way you can get your health bar to be pixel perfect.
Or if you want it to scale you can get a bit more control over exactly how it does this (for example pixel perfect with a detailed image that doesn’t scale when very close, changing to a simpler bar when further away, and then scaling this simple bar down the further away an enemy gets, finally cutting out at some clip distance).
Happy to post a simple example if you are interested.
using UnityEngine;
using System.Collections;
public class HealthBar : MonoBehaviour {
public float maxHealthBarSize;
public GameObject healthBar;
private float currentHealth;
private Camera guiCamera;
private Camera mainCamera;
public void Init(float maxHealthBarSize, Camera guiCamera, Camera mainCamera) {
this.maxHealthBarSize = maxHealthBarSize;
this.mainCamera = mainCamera;
this.guiCamera = guiCamera;
UpdateHealthBar(1.0f, 1.0f);
}
public void UpdatePosition(Vector3 worldPosition) {
Vector2 screenPoint = mainCamera.WorldToScreenPoint(worldPosition);
Vector3 worldPoint = guiCamera.ScreenToWorldPoint(new Vector3(screenPoint.x, screenPoint.y + 30, 20.0f));
transform.position = worldPoint;
}
public void UpdateHealthBar(float maxHealth, float currentHealth) {
Vector3 scale = healthBar.transform.localScale;
scale.x = maxHealthBarSize * (currentHealth / maxHealth);
healthBar.transform.localScale = scale;
if ((currentHealth / maxHealth) < 0.25f) {
healthBar.transform.GetChild(0).gameObject.renderer.material.color = Color.red;
} else if ((currentHealth / maxHealth) < 0.5f) {
healthBar.transform.GetChild(0).gameObject.renderer.material.color = new Color(1.0f, 0.5f, 0.25f, 1.0f);
}
}
}
You will need to set up a ‘GUI’ camera… and orthographic camera which clears depth only and renders on top of your scene.
You may want to add Init() to a Start method as well… I use another class to manage pooling of the health bars.
If you want to use the same rendering style you will also need to create a health bar object (the background image), and give it a child (the bar image). However you could just scale a single bar, or any other object if you wanted to rewrite UpdateHealthBar().
Call UpdatePosition() whenever enemy moves (or for a start every update).
mmm I think is will be much easier to just make the plane face the screen… I need would need to rotate it so its vector.forward is parallel to the camera vector.forward