Lifebars not appearing above enemies' heads

Hi guys,

I’m using the following script to show life bars above my game’s enemies, or at least that’s the intent:


using UnityEngine;
using System.Collections;

public class EnemyLifeBar : MonoBehaviour {

    public Transform target;
    public Vector3 offset = Vector3.up;
    public bool clampToScreen = false;
    public float clampBorderSize = 0.5f;
    public bool useMainCamera = true;
    public Camera cameraToUse;

    public Texture2D texture;
    public Rect fullRect;
    public float maxHealth = 100;
    public float currHealth = 100;

    private Camera cam;
    private Transform camTransform;
    private static Vector3 thisVector;

    // Use this for initialization
    void Start () {        
        thisVector = new Vector3(transform.position.x, transform.position.y, transform.position.z);       
        if (useMainCamera)
            cam = Camera.main;
        else
            cam = cameraToUse; 
    }

    //void OnGUI()
    //{
    //    print(string.Format("Vector [{0} ; {1} ; {2}]", thisVector.x, thisVector.y, thisVector.z));   

    //    float healthFrac = currHealth / maxHealth;
    //    Rect actualRect = new Rect(thisVector.x, thisVector.y, fullRect.width * healthFrac, fullRect.height);        

    //    GUI.BeginGroup(actualRect, texture);
    //    Rect innerRect = new Rect(0, 0, fullRect.width, fullRect.height);    
    //    GUI.DrawTexture(innerRect, texture);  
    //    GUI.EndGroup(); 
    //}

    void OnRenderObject()
    {
        print(string.Format("Vector [{0} ; {1} ; {2}]", thisVector.x, thisVector.y, thisVector.z));

        float healthFrac = currHealth / maxHealth;
        Rect actualRect = new Rect(thisVector.x, thisVector.y, fullRect.width * healthFrac, fullRect.height);

        GUI.BeginGroup(actualRect, texture);
        Rect innerRect = new Rect(0, 0, fullRect.width, fullRect.height);
        GUI.DrawTexture(innerRect, texture);
        GUI.EndGroup();    
    }

    // Update is called once per frame
    void Update () {

        camTransform = cam.transform; 
        if (clampToScreen) 
        {
            Vector3 relativePosition = camTransform.InverseTransformPoint(target.position);
            relativePosition = new Vector3(relativePosition.x, relativePosition.y, Mathf.Max(relativePosition.z, 1.0f));
            thisVector = cam.WorldToViewportPoint(camTransform.TransformPoint(relativePosition + offset));
            thisVector = new Vector3(Mathf.Clamp(thisVector.x, clampBorderSize, 1.0f - clampBorderSize),
                                         Mathf.Clamp(thisVector.y, clampBorderSize, 1.0f - clampBorderSize),
                                         thisVector.z);
        }
        else 
        {
            thisVector = cam.WorldToViewportPoint(target.position + offset);
        }
    }
}

The console prints out the following when I click the play button, with differing values for the vector:

`
Vector [-0.2314034 ; -2.436603 ; 0.2710707]
UnityEngine.MonoBehaviour:print(Object)
EnemyLifeBar:OnRenderObject() (at Assets/Entities/Enemies/Scripts/EnemyLifeBar.cs:46)
`

The script is attached to an enemy prefab, with the slots set as follows:

Target: Pitbull
Offset: (0,0, 0)
Clamp to Screen: false
Clamp Border Size: 0.5
Use Main Camera: true
Camera to Use: None (Camera)
Texture: EnemyLifeBar
Full Rect: (0, 0, 2, 1)
Max Health: 100
Curr Health: 100

The problem is that when I press play, I get a strange thing where a green rectangle (the health bar), and only one of them, appears in strange locations on the screen, seemingly unconnected with the enemies in the scene, with only one bar appearing at a time. The bar doesn’t appear directly above the nearest enemy’s head, for example. Moreover, trying to scale it down (because it’s way too big) merely causes it to go away. What’s going on? Should I attempt to take a new approach to enemy life bars, using the following Player Life Script as a reference?

`

using UnityEngine;
using System.Collections;

public class PlayerLifeBar : MonoBehaviour 
{

	public int maxHealth = 100;
	public int curHealth = 100;
	
	public float healthBarLength;
	
	public Font healthBarFont;
	
	// Use this for initialization
	void Start () 
	{
		healthBarLength = Screen.width / 2;
	}
	
	// Update is called once per frame
	void Update () 
	{
		AdjustCurrentHealth(0);
	}
	
	void OnGUI() 
	{
		GUI.skin.box.font = healthBarFont;
	
		GUI.Box(new Rect(10, 10, Screen.width / 2 / (maxHealth / curHealth), 40), curHealth + "/" + maxHealth);
		
	}
	
	public void AdjustCurrentHealth(int adj)
	{
		curHealth += adj;
		
		if (curHealth <= 0)
			SendMessage("Die");
		
		if (curHealth > maxHealth)
			curHealth = maxHealth;
		
		if(maxHealth < 1)
			maxHealth = 1;
		
		healthBarLength = (Screen.width / 2 ) * (curHealth / (float)maxHealth);
	}
}
`

MachCUBED

There is a really useful script in the Wiki if you haven’t seen it. It’s an easy label solution which makes a GUI label follow a 3D object in model space. This way the label attributes can be adjusted (stay the same size, shrink when the character goes far away, stay on the screen if the character wanders off screen (for airplane games) etc… )

Check it out

I found an answer on YouTube:

This script can be adapted with an adjust health function and it should work.

You could also try using the ObjectLabel as a “football”, i.e. attach it to an empty object and change it’s transform to the transform of the closest enemy. just an alternate method…