Walkthrough for a solution for the health bar rotation problem

rpg

#1

Hello everyone, there has been a while since the last time that I’ve posted anything useful here, I’ve been lurking more in the discord this past year, doing my best to support the community in there instead.

I’d like to share another way to make the health bar UI to be always “pointing” to the camera. The downside of the way that is presented in the course is that once the healthbar deviates too much from the center of the screen, it will not only rotate towards the camera, but it will also kind of rotates in its own axis a bit, which is undesirable:

My method consists of a health bar that “lives” in the canvas and that has a reference to the transform of the entity that needs it, this way it can ask the camera where the target object is in relation to the screen position and then use this information to update it’s position in the canvas, this results in a Health bar that won’t ever rotate and with consistent size:

How to do it:

  1. Create a canvas (screen space) to hold the health bars, the code below is just a small class in the canvas just to facilitate for other classes to find it through the script type:
public class HealthBarCanvas : MonoBehaviour
{
	public RectTransform rectTransform
	{
		get
		{
			if (_rectTransform== null)
				_rectTransform = GetComponent<RectTransform>();
			return _rectTransform;
		}
	}
	RectTransform _rectTransform;
}
  1. The entity that requires the Health Bar will instantiate it in its own start method, and save the reference to the health bar so it can be updated afterwards (you can use pooling for that too, but this isn’t the focus of this post):
public class Enemy : MonoBehaviour
{
	public HealthBar healthBarPrefab;

	void Start()
	{
		healthBarPrefab = Instantiate(healthBarPrefab, transform.position, Quaternion.identity);
		healthBarPrefab.StartBar(gameObject);
	}
}
  1. Now you need to create the health bar prefab, it’s basically one regular health bar image for the background and as child another image for the fill, the RectTransform of the health prefab should have its anchors and pivots at the position 0.5x and 0.5y, position set to zero and the size as the desired size for it to have on screen:

  1. Attached to this Health bar prefab, there is the script that communicates with both the canvas and the entity that will use it;
using UnityEngine;
using UnityEngine.UI;

public class HealthBar : MonoBehaviour
{
	public Image healthSprite;
	GameObject target;
	RectTransform rectTransform;
	[Range(0, 5)] public float healthBarUpOffset;
	RectTransform canvasRectTransform;

	// First you retrieve the information about the position in the world that you want it to be, you can add an offset like I did in order to make it always be on top of the target entity
	void Update()
	{
		Vector3 worldTargetPosition = target.transform.position + Vector3.up * healthBarUpOffset;
		rectTransform.position = Camera.main.WorldToScreenPoint(worldTargetPosition);
	}

	// This method starts the Health Bar, setting the healthbarcanvas as it's parent and setting the entity that created it as it's target
	public void StartBar(GameObject target)
	{
		rectTransform = GetComponent<RectTransform>();
		canvasRectTransform = FindObjectOfType<HealthBarCanvas>().rectTransform;
		transform.SetParent(canvasRectTransform);
		this.target = target;
	}

	// simple example method to update the health bar value
	public void UpdateValue(float value)
	{
		healthSprite.fillAmount = value;
	}
}

You can download this sample package that I’ve uploaded in here:
Health Bar Package

Let me know your thoughts about it and if there is any doubt.


#2

Just to point out, there is a mistake in the enemy class code, the reference to the healthbar instance should ideally be a different variable instead of the same that holds the prefab


#3

thanks a truly brilliant method :slight_smile: it totally would not have occurred to me thanks for sharing it.


#4

Thanks :smiley:
I’m glad to know that you liked the method. I Hope it to be of use to someone.