• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by MachCUBED · Jan 22, 2012 at 04:47 PM · transformspritebehaviorlifebar

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

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by MachCUBED · Feb 01, 2012 at 11:16 PM

I found an answer on YouTube:

http://www.youtube.com/watch?v=iER_LFwi1-U

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

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
1

Answer by KrisCadle · Jan 22, 2012 at 10:44 PM

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 http://unifycommunity.com/wiki/index.php?title=ObjectLabel

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image MachCUBED · Jan 23, 2012 at 08:24 PM 0
Share

I added the Javascript version of ObjectLabel, and then set Clamp to Screen to true. I have one GUILabel, and it's currently set to follow one of my enemies (and only one of them) around, by way of setting said enemy as the target. I tried editing the script to look like this:

var target : Transform; // Object that this label should follow var offset = Vector3.up; // Units in world space to offset; 1 unit above object by default var clampToScreen = false; // If true, label will be visible even if object is off screen var clampBorderSize = .05; // How much viewport space to leave at the borders when a label is being clamped var use$$anonymous$$ainCamera = true; // Use the camera tagged $$anonymous$$ainCamera var cameraToUse : Camera; // Only use this if use$$anonymous$$ainCamera is false private var cam : Camera; private var thisTransform : Transform; private var camTransform : Transform;

function Start () { thisTransform = transform; if (use$$anonymous$$ainCamera) cam = Camera.main; else cam = cameraToUse; camTransform = cam.transform; }

// Find the closest enemy function FindClosestEnemy() : GameObject { // Find all game objects with tag Enemy var gos : GameObject[]; gos = GameObject.FindGameObjectsWithTag("Enemy"); var closest : GameObject; var distance = $$anonymous$$athf.Infinity; var position = transform.position; // Iterate through them and find the closest one for (var go : GameObject in gos) { var diff = (go.transform.position - position); var curDistance = diff.sqr$$anonymous$$agnitude; if (curDistance < distance) { closest = go; distance = curDistance; } } return closest; }

function Update () {

 enemy = FindClosestEnemy();
 go = enemy.transform;
 
 if (clampToScreen) {
     var relativePosition = camTransform.InverseTransformPoint(target.position);
     relativePosition.z = $$anonymous$$athf.$$anonymous$$ax(relativePosition.z, 1.0);
     thisTransform.position = cam.WorldToViewportPoint(camTransform.TransformPoint(relativePosition + offset));
     thisTransform.position = Vector3($$anonymous$$athf.Clamp(thisTransform.position.x, clampBorderSize, 1.0-clampBorderSize),
                                      $$anonymous$$athf.Clamp(thisTransform.position.y, clampBorderSize, 1.0-clampBorderSize),
                                      thisTransform.position.z);
 }
 else {
     thisTransform.position = cam.WorldToViewportPoint(target.position + offset);
 }

}

@script RequireComponent(GUIText)

The idea is to make it follow whichever enemy is closest to the player. The problem is that the script only works without errors if the target is set to a given enemy in the editor (and it will only follow that enemy). However, if I don't set the target, I get a bunch of errors and a label that won't follow any of my enemies. In sort, you helped me with one problem, but I ended up with another one.

avatar image MachCUBED · Jan 24, 2012 at 04:29 AM 0
Share

I tried the following code for life bars above my enemies' heads:

using UnityEngine; using System.Collections;

public class EnemyLifeBar : $$anonymous$$onoBehaviour {

 public Transform target;  // Object that this label should follow
 public Vector3 offset = Vector3.up;    // Units in world space to offset; 1 unit above object by default
 public bool clampToScreen = false;  // If true, label will be visible even if object is off screen
 public float clampBorderSize = 0.05f;  // How much viewport space to leave at the borders when a label is being clamped
 public bool use$$anonymous$$ainCamera = true;   // Use the camera tagged $$anonymous$$ainCamera
 public Camera cameraToUse ;   // Only use this if use$$anonymous$$ainCamera is false
 
 public int maxHealth = 100;
 public int curHealth = 100;
 
 public float healthBarLength;
 
 public Font healthBarFont;
 
 Camera cam;
 Transform thisTransform;
 Vector3 thisVector;
 Transform camTransform;

 void Start () 
 {
     healthBarLength = 200;
     
      thisVector = new Vector3(transform.position.x, transform.position.y, transform.position.z);
     if (use$$anonymous$$ainCamera)
         cam = Camera.main;
     else
         cam = cameraToUse;
 }
 void OnGUI() 
 {
     GUI.skin.box.font = healthBarFont;
 
     GUI.Box(new Rect(thisVector.x, thisVector.y, healthBarLength / (maxHealth / curHealth), 20), curHealth + "/" + maxHealth);
 }

 void Update()
 {

     camTransform = cam.transform; 
     
     if (clampToScreen) 
     {
         Vector3 relativePosition = camTransform.InverseTransformPoint(target.position);
         relativePosition = new Vector3(relativePosition.x, relativePosition.y, $$anonymous$$athf.$$anonymous$$ax(relativePosition.z, 1.0f));
         thisVector = cam.WorldToViewportPoint(camTransform.TransformPoint(relativePosition + offset));
         thisVector = new Vector3($$anonymous$$athf.Clamp(thisVector.x, clampBorderSize, 1.0f - clampBorderSize),
                                      $$anonymous$$athf.Clamp(thisVector.y, clampBorderSize, 1.0f - clampBorderSize),
                                      thisVector.z);
     }
     else 
     {
         thisVector = cam.WorldToViewportPoint(target.position + offset);
     }
 }
 
 public void AdjustCurrentHealth(int adj)
 {
     curHealth += adj;
     
     if (curHealth <= 0)
         Send$$anonymous$$essage("Die");
     
     if (curHealth > maxHealth)
         curHealth = maxHealth;
     
     if(maxHealth < 1)
         maxHealth = 1;
     
     healthBarLength = healthBarLength * (curHealth / (float)maxHealth);
 }

}

It causes the enemies' small life bars to appear in the upper left-hand corner of the screen, with very little movement no matter what. This is an issue whether or not screen clamping is enabled. What is wrong with my above code?

avatar image
0

Answer by KrisCadle · Mar 09, 2012 at 07:53 PM

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...

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.



Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

My Y position goes fixed to some value 0 Answers

The name 'Joystick' does not denote a valid type ('not found') 2 Answers

How To Move GameObjects In Fixed Path? 1 Answer

How to remove z axis control from script 1 Answer

Can someone help me fix my Javascript for Flickering Light? 6 Answers

  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges