Tasharen Entertainment Forum

Support => NGUI 3 Support => Topic started by: ArenMook on April 20, 2012, 10:04:01 PM

Title: So you want to make health bars...
Post by: ArenMook on April 20, 2012, 10:04:01 PM
Since I get a question about this roughly once a day...

Video: http://www.youtube.com/watch?v=idVr8-jfdAI

Code: (below... scroll down)
Title: Re: So you want to make health bars...
Post by: Sarus on May 13, 2012, 04:46:40 AM
Hi Aren,

If we wanted the health bars to get larger and smaller as you move closer and further away from the GameObject they are floating over (in this case the coins), what changes would be required?  Is there a way to get this effect with a 2d UI (have the bars scale based on distance from a GameObject), or do we need to use a 3d UI?

Thanks!  Also, thank you for providing the example project found in that thread.  Very useful.

~Ed
Title: Re: So you want to make health bars...
Post by: ArenMook on May 13, 2012, 06:23:01 AM
Keeping them in 2D and adjusting their Z as well as scaling them is generally easier as then you can also make sure that they stay relatively proper (not too small or not too big).
Title: Re: So you want to make health bars...
Post by: Sarus on May 15, 2012, 08:27:48 PM
If we go with the method of scaling a 2d UI element based on distance from the game camera there's no way to do depth testing with in game objects right?
Title: Re: So you want to make health bars...
Post by: ArenMook on May 15, 2012, 09:26:34 PM
Nope, for that you need to keep your widgets in 3D.
Title: Re: So you want to make health bars...
Post by: tinyutopia on June 21, 2012, 04:47:09 PM
I'm scaling my health bar sliders with this this code:

  1.         public void UpdateDisplay( float x) {
  2.                 if( x < 0 )
  3.                         x = 0;
  4.                 else if( x > 1 )
  5.                         x = 1;
  6.                        
  7.                 _slider.foreground.localScale = new Vector3( _maxWidth * x, _slider.foreground.localScale.y, _slider.foreground.localScale.z );
  8.                 oldxp = GameManager.Instance.curxp;
  9.         }

The problem is that whenever x = 0, when I view the health bar on my build, it distorts stretching the sprite across the screen where it terminates somewhere in the center of the game view. Not sure why this is happening, maybe I just need to disable this sprite if x = 0. Is there a better way?
Title: Re: So you want to make health bars...
Post by: ArenMook on June 21, 2012, 05:19:27 PM
Don't scale the sprite. Scale the parent game object. I also suggest scaling uniformly -- that is scale X, Y, and Z by an equal amount. Lastly, if X is 0, then your scale becomes 0. That's invalid to begin with. I suggest adding min/max.
Title: Re: So you want to make health bars...
Post by: Bantis on August 20, 2012, 07:33:54 PM
Any chance of this getting reposted? The link just takes you to the front page of the site.
Title: Re: So you want to make health bars...
Post by: ArenMook on August 20, 2012, 08:20:17 PM
I had to take down the old forum as it had a security hole in it, which is why that page no longer exists. I'll see if I can find the code for it later, although HUDText extension does the whole "UI component following a 3D object" thing pretty well. Slap a slider on there, and you've got a health bar above the unit's head.
Title: Re: So you want to make health bars...
Post by: gamesonytablet on September 05, 2012, 07:50:48 AM
Hi, still looking for the original code? Even though the HUDText approach is interesting as well, I have a blog post that introduced this functionality in Japanese, and my access log tells me there are people looking for how to implement this literally every day.
I'm assuming there are others looking for this as well. (like me!   :'()
Title: Re: So you want to make health bars...
Post by: ArenMook on September 05, 2012, 03:35:15 PM
This goes on the 3D game object, and should reference a prefab you've created for the Unit's HUD object that has a UnitHUD script on it:
  1. using UnityEngine;
  2.  
  3. /// <summary>
  4. /// Example script that instantiates a HUD window that will follow this game object.
  5. /// </summary>
  6.  
  7. [AddComponentMenu("NGUI/Examples/Add Unit HUD")]
  8. public class AddUnitHUD : MonoBehaviour
  9. {
  10.         public GameObject prefab;
  11.  
  12.         void Start ()
  13.         {
  14.                 if (prefab != null)
  15.                 {
  16.                         UICamera cam = UICamera.FindCameraForLayer(prefab.layer);
  17.  
  18.                         if (cam != null)
  19.                         {
  20.                                 GameObject go = cam.gameObject;
  21.                                 UIAnchor anchor = go.GetComponent<UIAnchor>();
  22.                                 if (anchor != null) go = anchor.gameObject;
  23.  
  24.                                 GameObject child = GameObject.Instantiate(prefab) as GameObject;
  25.                                 Transform t = child.transform;
  26.                                 t.parent = go.transform;
  27.                                 t.localPosition = Vector3.zero;
  28.                                 t.localRotation = Quaternion.identity;
  29.                                 t.localScale = Vector3.one;
  30.  
  31.                                 UnitHUD hud = child.GetComponent<UnitHUD>();
  32.                                 if (hud != null) hud.target = transform;
  33.                         }
  34.                         else
  35.                         {
  36.                                 Debug.LogWarning("No camera found for layer " + LayerMask.LayerToName(prefab.layer), gameObject);
  37.                         }
  38.                 }
  39.                 Destroy(this);
  40.         }
  41. }
This goes on the HUD object -- a UI prefab that you want to follow your unit. This is where you'll place such things as health bars, unit name, etc.
  1. using UnityEngine;
  2.  
  3. /// <summary>
  4. /// Example script showing how to add UI window that follows an object drawn by another camera.
  5. /// </summary>
  6.  
  7. [AddComponentMenu("NGUI/Examples/Unit HUD")]
  8. public class UnitHUD : MonoBehaviour
  9. {
  10.         /// <summary>
  11.         /// Target object this UI element should follow.
  12.         /// </summary>
  13.  
  14.         public Transform target;
  15.  
  16.         Transform mTrans;
  17.         Camera mGameCam;
  18.         Camera mUICam;
  19.         Vector3 mPos;
  20.         bool mVisible = true;
  21.  
  22.         void Start ()
  23.         {
  24.                 if (target == null) { Destroy(gameObject); return; }
  25.                 mTrans = transform;
  26.                 mGameCam = NGUITools.FindCameraForLayer(target.gameObject.layer);
  27.                 mUICam = NGUITools.FindCameraForLayer(gameObject.layer);
  28.         }
  29.  
  30.         void LateUpdate()
  31.         {
  32.                 if (target == null) { Destroy(gameObject); return; }
  33.  
  34.                 mPos = mGameCam.WorldToViewportPoint(target.position);
  35.  
  36.                 bool visible = (mPos.z > 0f && mPos.x > 0f && mPos.x < 1f && mPos.y > 0f && mPos.y < 1f);
  37.  
  38.                 if (mVisible != visible)
  39.                 {
  40.                         mVisible = visible;
  41.                         UIWidget[] widgets = gameObject.GetComponentsInChildren<UIWidget>();
  42.                         foreach (UIWidget w in widgets) w.enabled = mVisible;
  43.                 }
  44.                
  45.                 if (mVisible)
  46.                 {
  47.                         mPos = mUICam.ViewportToWorldPoint(mPos);
  48.                         mPos.z = 0f;
  49.                         mTrans.position = mPos;
  50.                 }
  51.         }
  52. }
Title: Re: So you want to make health bars...
Post by: gamesonytablet on September 05, 2012, 07:36:07 PM
Thanks for your quick action! ;)
Title: Re: So you want to make health bars...
Post by: SketchWork on September 07, 2012, 02:33:24 PM
The link on your first post no longer works for some reason.
Title: Re: So you want to make health bars...
Post by: ArenMook on September 07, 2012, 03:49:36 PM
Yup, I reposted the code later in the thread.
Title: Re: So you want to make health bars...
Post by: capitalj on September 28, 2012, 05:20:50 PM
How would I adjust this code to make a health bar or HUD item that uses a 3D NGUI camera? I tried the same code but the HUD object is just positioned at the same world position as the targetTransform (meaning that it is no longer visible by the 3D NGUI camera).
Title: Re: So you want to make health bars...
Post by: ArenMook on September 28, 2012, 09:39:30 PM
For a 3D UI you don't need this. Assuming your health bar is just an object in 3D space, just put a FaceCamera script on it.
Title: Re: So you want to make health bars...
Post by: capitalj on October 07, 2012, 03:20:10 PM
But as the camera that is attached to the UI Root(3D) is not in the same position as the main game camera (that renders the gameobject that I want to add a HUD to), then any 3D UI that it renders won't be in the same position as the gameobject it is tracking. Should I make another NGUI hierarchy that then has a camera that matches the main game camera and renders those types of UI elements?

Or should I attach the NGUI widgets straight to my main game camera so that the 3D UI and the gameobjects are rendered together?

-JJ
Title: Re: So you want to make health bars...
Post by: ArenMook on October 07, 2012, 07:26:06 PM
The latter: attach the NGUI widgets straight to your 3D game objects.
Title: Re: So you want to make health bars...
Post by: terence on October 09, 2012, 01:23:47 AM
I've been to trying to get a floating health bar on a 3D object to work right. I followed the code in this discussion but the results are less then satisfactory. The UISlider seems to float around the 3D object rather than staying in place.

Info:
1) I am using a simple 2D U. Should I switch to a 3D UI and attach the widgets to my 3D object with a face camera script?
2) I am attaching the uislider to parent to the panel->anchor->camera->uiroot(2d)

Attached some images that might help explain thing. The first is my ui hierachy. The second is the picture of the initial position of the uislider and the third when i have moved the game camera around to the left. It seems to uislider widget seems to float around the object and not stay exact.
Title: Re: So you want to make health bars...
Post by: ArenMook on October 09, 2012, 05:19:49 PM
Seems to me that it does exactly what it should. You told it to follow an object that has its position slightly below the ground, and your widget's origin is left-aligned.
Title: Re: So you want to make health bars...
Post by: darthbator on November 10, 2012, 07:10:26 PM
I think I posted this on the old forums but I am still having issues getting 2D simple UI elements to track (or even reliably be placed at) 3D scene elements. Here let me show you :) Here's the script I am using to just try and place something in an expected position at start.

  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class posBar : MonoBehaviour {
  5.         public Transform actorPos;
  6.         public Camera guiCam;
  7.        
  8.         void Start () {
  9.                 guiCam = NGUITools.FindCameraForLayer((int)Layers.Index.screeInterface);
  10.                 Vector3 atmp = Camera.main.WorldToViewportPoint(actorPos.position);
  11.                 atmp.z = 0;
  12.                 Vector3 btmp = guiCam.ViewportToWorldPoint(atmp);
  13.         Debug.Log("ViewOBJ " + atmp.ToString() + "WorldBar " + btmp.ToString());
  14.                 transform.position = btmp;     
  15.         }
  16. }

However my UI elements are ALWAYS being positioned outside of the view of my UI camera. The Z value in particular seems to be tremendously off. What I a most confused about is what is coming out of that debug statement and the actual value of the transform in the editor...

ViewOBJ (3.0, 0.5, 0.0)WorldBar (9.0, 100.0, 0.0)FinalPos (0.5, 100.2, 0.0)

However that doesn't appear to be the value the bar is getting at all.... Check out the attached image....

Why is that happening? I have the UI root placed at worldOrigin + 100. Based on that all the numbers in the debug look correct but I am getting some really out there Z value that is totally throwing my bar out of my UI frame. What am I doing wrong? How am I getting that crazy z value?

Title: Re: So you want to make health bars...
Post by: ArenMook on November 11, 2012, 10:58:46 AM
With a 3D camera you don't need this. Just make each health bar object a child of our game object, having its own panel, and a face camera script attached. No UI camera necessary.
Title: Re: So you want to make health bars...
Post by: darthbator on November 12, 2012, 05:52:59 PM
I noticed when I billboard the bars towards the camera with the LookTarget script the bars themselves start to look really jaggy... However when using a dedicated UI camera I am not having this issue (both my game and UI cameras where ortho so that has not changed). Is there any way to mitigate that jagginess without the AA image filter from pro?
Title: Re: So you want to make health bars...
Post by: ArenMook on November 12, 2012, 07:06:34 PM
Jagginess when it's rotated, you mean? You can just have thicker (and softer) borders.
Title: Re: So you want to make health bars...
Post by: darthbator on November 26, 2012, 04:47:28 PM
What I noticed is that it's not really just jagniess it's that the bars are not "flat" when they are facing the camera making them look really off as they rotate to face the camera and everything moves around the environment. This is why I had initially been using a second camera for the UI. That way I could keep the elements "flat". Maybe there's something I am missing?
Title: Re: So you want to make health bars...
Post by: ArenMook on November 26, 2012, 05:36:29 PM
3D camera has perspective, so things will look like that. If you want it to always be flat, you need a 2D camera, yes.
Title: Re: So you want to make health bars...
Post by: AXE on January 14, 2013, 09:33:26 AM
I'm using this technique to draw an UILabel with a number over 3D objects in my scene, but I have a problem. Here's the code I'm using:

  1. GameObject selNumberLabel = NGUITools.AddChild(GameObject.Find("SelectionNumbers"), (GameObject)Resources.Load("SelectionNumber"));
  2.     selNumberLabel.GetComponent<UILabel>().text = selIndex.ToString();
  3.    
  4.     Camera gameCam = NGUITools.FindCameraForLayer(realCard.layer);
  5.     Camera UICam = NGUITools.FindCameraForLayer(selNumberLabel.layer);
  6.    
  7.     Vector3 pos = gameCam.WorldToViewportPoint(realCard.transform.position);
  8.         Debug.Log("GameCam pos:" + pos.ToString());
  9.     pos = UICam.ViewportToWorldPoint(pos);
  10.         Debug.Log("UICam pos: " + pos.ToString());
  11.     pos.z = 0;
  12.         Debug.Log("Final pos: " + pos.ToString());
  13.    
  14.     selNumberLabel.transform.position = pos;
  15.         NGUITools.MakePixelPerfect(selNumberLabel.transform);

The objects this label is instantiated into ("SelectionNumbers") is a simple empty GO which is under an Anchor GO (Anchor Center). The position of the empty GO ("SelectionNumbers") is: X = 0, Y = 0, Z = 321. Once the code above gets executed, I'd espect to find the newly instantiated label at X = pos.x, Y = pos.Y, Z = 0. Instead, it always gets a Z = -320.

The debug messages spit out these messages:

1) GameCam pos:(0.7, 0.3, 2.8)
2) UICam pos: (0.7, -0.4, 2.8)
3) Final pos: (0.7, -0.4, 0.0)

The Z should be 0...

Any help?
Title: Re: So you want to make health bars...
Post by: Scathis on January 23, 2013, 05:44:22 PM
Update #2: I found the issue. Took some debug but my main camera was not culling out the UI and therefore returning as the UI camera. Thus the poor offset.

Ok, I'm stumped.

I have:
A 3D Camera for my main camera that can be dragged around.
A UIRoot(2D) with a camera for the UI. UIRoot is located off to the side at (0,0,200)
I have a panel called "PANEL_DYNAMIC" that I parent all my dynamic UI elements to, mostly progress bars. Panel is a child of an object that has an anchor anchoring to the top left. All other position transforms are (0,0,0) and scales are (1,1,1)
I have a UIBarPrefab that is a prefab that has a UIFollowTarget script on it and a child with a label and another child with a progressbar.

This is my code for creating a bar inside the object I want it to follow:
  1. void CreateBarObject()
  2. {
  3.         GameObject pnl = GameObject.Find ("PANEL_DYNAMIC");
  4.         barObject = NGUITools.AddChild( pnl, UIBarPrefab );
  5.         barObject.GetComponent<UIFollowTarget>().target = transform;
  6. }
  7.  

The bar isn't showing up in the right position.
When I look at the update function for UIFollowTarget the barObject position calculates to (10.5,0.0, -1.5) but it's localPosition ends up being (4544.5, -378.8, 0). I'm not sure why. That's way off screen.

Update: No matter how I move around the object on the screen the position/locationposition doesn't change.
I verified the UIFollowTarget script is on the progress bar that gets created but it just doesn't follow the target.

What am I doing wrong? I've combed through as much documentation as I could find.
Title: Re: So you want to make health bars...
Post by: Kiu on February 21, 2013, 11:43:05 AM

Thanks for this code, it's working great. I just have one more problem.
I'm using UIlabels for a Augmented Reality App. I'd like to align the label Rotation to the camera z-Rotation so that the labels point to the camera "up" no matter what orientation relative to the screen.

I've tried the euler Angles, but they keep jumping and I'm not really getting how to handle quaternions properly yet.

How would I do this?
Title: Re: So you want to make health bars...
Post by: hello@patrikstas.com on May 01, 2013, 03:00:29 PM
Hey guys, I need your advice how to achieve bar of different shape. I attach pictures so you have clear idea what exactly I need. I mean some more elegant solution than making tons of pictures with different level of progress. Any advice appreciated, thank you.
Title: Re: So you want to make health bars...
Post by: ArenMook on May 02, 2013, 03:40:58 AM
2 sprites. Bottle sprite, and on top of it your blue liquid sprite. The liquid sprite should be a filled sprite set to a vertical fill.
Title: Re: So you want to make health bars...
Post by: wqf525 on May 13, 2013, 08:19:44 AM
 :) :) there is no link to download the latest or other plugin,I want to get one, I support tasharen
Title: Re: So you want to make health bars...
Post by: Nicki on May 18, 2013, 07:08:20 AM
wgf525: You can buy it on the Asset Store in Unity3D.
Title: Re: So you want to make health bars...
Post by: Giantbean on September 11, 2013, 10:32:44 AM
With a 3D camera you don't need this. Just make each health bar object a child of our game object, having its own panel, and a face camera script attached. No UI camera necessary.

When I do this the item becomes a simple billboard and loses any click options or drop down menus. How do I attach the GUI to a floating point on a game object and still make it click-able?
Title: Re: So you want to make health bars...
Post by: ArenMook on September 11, 2013, 05:03:28 PM
You need a UICamera script on your main camera as well.