The enemy health bars in world space look really too weird, so I reused what I did for Realm Rush in the 3D course: display them in the overlay canvas.
Script to attach to the enemies, and link an health bar prefab (the image only, not the canvas) to it.
EDIT: Forgot about the EnemyHealthBar.cs script attached to the Enemy Health Bar prefab!
It does not work anymore since the health bar is now child of the canvas instead of the enemy.
We need to merge the code of EnemyHealthBar.cs with the new script:
using UnityEngine;
using UnityEngine.UI;
public class HealthBarFloatOverlay : MonoBehaviour
{
[SerializeField] RawImage healthBarPrefab;
[SerializeField] float verticalOffsetFactor = 0.08f;
Vector2 screenPos; // Enemy position in Screen space coordinates
RawImage healthBarImage; // The instantiated health bar object
Enemy enemy = null;
void Start()
{
// Get the canvas to set it as parent of the health bars
GameObject canvasObj = GameObject.Find("Game Canvas");
Canvas canvas = canvasObj.GetComponent<Canvas>();
// Get the Enemy component to update the health bar with enemy's health
enemy = GetComponent<Enemy>();
HealthBarInit(canvas);
}
void HealthBarInit(Canvas canvas)
{
// Instantiate the health bar object (type Image), child of the canvas
healthBarImage = Instantiate(healthBarPrefab, screenPos, Quaternion.identity, canvas.transform);
}
void Update()
{
UpdateHealthBarPosition();
UpdateBarWithHealthValue();
}
private void UpdateHealthBarPosition()
{
// Convert the enemy 3D position to 2D screen position
screenPos = Camera.main.WorldToScreenPoint(transform.position);
// Calculate a vertical offset independent of the screen resolution to place the health bar above the enemy
float offset = verticalOffsetFactor * Screen.height;
healthBarImage.transform.position = screenPos + new Vector2(0, offset);
}
private void UpdateBarWithHealthValue()
{
float xValue = -(enemy.healthAsPercentage / 2f) - 0.5f;
healthBarImage.uvRect = new Rect(xValue, 0f, 0.5f, 1f);
}
}