Search Unity

Health Bar UI

Discussion in 'Immediate Mode GUI (IMGUI)' started by stunriver, Mar 5, 2010.

  1. stunriver

    stunriver

    Joined:
    Mar 5, 2010
    Posts:
    10
    Hi, I would like to know if anyone know how to do Resident Evil 5 Health bar GUI style which doing in circle.

    Is there a way to just use 2 pictures or maybe 4 at the most to do this style of health Bar UI.

    I read about advanced health bar which is in traditional long rectangle, it only need 2 picture and scale the full health bar and leave the empty health bar under the full health, so it would animate as if the full health is reduced to 0. but mine is circle, and I need to know how to do the scaling or masking so it does the same thing as the rectangle.

    Help is really appreciated Thanks
     

    Attached Files:

  2. stunriver

    stunriver

    Joined:
    Mar 5, 2010
    Posts:
    10
    I'm a newbie in scripting, so please be patient to me as well. Thanks
     
    Unity Ninja likes this.
  3. SilverFoxMedia

    SilverFoxMedia

    Joined:
    Nov 7, 2009
    Posts:
    153
    I believe the method you're after is explained in the 3D Platformer Tutorial (Around Page 53) as far as I know the method in the tutorial is the easiest way to do it.

    Sorry if this isn't any help.
     
  4. stunriver

    stunriver

    Joined:
    Mar 5, 2010
    Posts:
    10
    thanks for the reply I was going to do 50 pictures of them from full health to 0 health, but a friend of mine said I dont need 50 pictures I can just have few pictures and do masking instead. the Method shown in the pdf is using 6 different pictures for 6 pie, while I will have 50 different pictures, where she said it would make it laggy. I appreciate your answer it makes me a little bit more confident that there is no other way. But I hope there is somebody else who cares to share if they have an idea.
     
  5. cerebrate

    cerebrate

    Joined:
    Jan 8, 2010
    Posts:
    261
    I use the multiple images for mine, and I have about 180 images for (each) of my circles. This is how I did it:

    First, I made the bars/circles whatnot in my 3d editor of choice, then animated the bars/circles so that it would appear that they filled up. I rendered the animation out as an image sequence so I would have an individual image for each amount.

    Made a helper function to load a specified sequence of images into an array from the Resources folder, so that I didn't have to click/drag each image into a slot on a texture array:

    Code (csharp):
    1. //loads a sequence of images from Resources folder. Expects images to be numbered from 0001 to (maximum) 9999.
    2. //Returns the image sequence as an array
    3. //filetype doesn't matter, as Resources.Load doesn't take a filetype (you leave it out of the the name)
    4. public static function LoadSequence(namePrefix : String, length : int) : Array{
    5.     var bars = Array(length);
    6.     var i=0;
    7.     for (i=0;i<length;i++)
    8.     {
    9.         var j = i + 1;
    10.         if (j < 10){
    11.             //Debug.Log("loading " + namePrefix + "000" + j);
    12.             bars[i] = Resources.Load(namePrefix + "000" + j, Texture);
    13.         }
    14.         else if (j < 100){
    15.             //Debug.Log("loading " + namePrefix + "00" + j);
    16.             bars[i] = Resources.Load(namePrefix + "00" + j, Texture);
    17.         }
    18.         else if (j < 1000){
    19.             bars[i] = Resources.Load(namePrefix + "0" + j, Texture);
    20.         }
    21.         else{
    22.             bars[i] = Resources.Load(namePrefix + j, Texture);
    23.         }
    24.     }
    25.     return bars;
    26. }
    to use this, I have something like this (EGUI was the script the loader function was in):

    Code (csharp):
    1.  
    2. private var quarterCircleValues = [];
    3.  
    4. function Awake() {
    5.     quarterCircleValues = EGUI.LoadSequence("quarterCircleValue_", 180);
    6. }
    7.  
    As you can see, it loads a sequence of images named from quarterCircleValue_0001 to quarterCircleValue_0180 into an array.

    Then, I access just the index of the array that I want to based upon the percentage of health/ammo/whatever remaning.

    Code (csharp):
    1.  
    2. function OnGUI(){
    3.    var smallLeftIndex = Mathf.RoundToInt((quarterCircleValues.length-1)*weaponsController.HandLaserCharge());
    4.  
    5.  
    6.    GUI.DrawTexture(Rect (scrWdth - isi, mainpos.y - isi, isi, isi), quarterCircleValues[smallLeftIndex]);
    7. }

    It takes a second on starting a level to load all the textures into the array, but once it is done, it's still quite fast. It looks great too, as it makes the circle smoothly increment/decrement. It is probable you could even speed this up by using a Texture[] instead of a general Array, but I'm unsure how to work with those currently.
     
  6. stunriver

    stunriver

    Joined:
    Mar 5, 2010
    Posts:
    10
    Thank you for your respond, I will try to do your idea, thanks again
     
  7. huxley

    huxley

    Joined:
    Apr 27, 2009
    Posts:
    334
    I actually think that you were on the right path with the masking option. You would need the pro version though, because it would require a render to texture.

    Sorry, don't know the math for it. Good luck.
     
  8. ProtonOne

    ProtonOne

    Joined:
    Mar 8, 2008
    Posts:
    406
    Here's an idea. Do the red ring as the background, then do the just the green ring over top of it. Give the green ring a gradient on the alpha channel in the direction you want the health meter to go. Assign a Transparent/Cutout shader to the green circle. Drag the cutoff value to make the circle grow and shrink.

    Can't do any of this with the OnGUI stuff. Need to use actual polygons so you can change the shader.
     
  9. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Yes, that's the way to do it. For example, this (web player). There are two textures; one for the regular graphics (using normal alpha for nice anti-aliasing) and one for the health bar (using alpha cutoff). The health bar's alpha looks like this:



    The non-alpha part of the texture is just a block of solid green.

    The code is this:

    Code (csharp):
    1. function Update () {
    2.     renderer.material.SetFloat("_Cutoff", Mathf.InverseLerp(0, Screen.width, Input.mousePosition.x));
    3. }
    This is much faster, easier, and less memory-using than having an array of circular textures. :)



    --Eric
     
    rakkarage likes this.
  10. cerebrate

    cerebrate

    Joined:
    Jan 8, 2010
    Posts:
    261
    Ah, that is an interesting idea. However:

    My texture array is capable of changing shape, size, and color. He probably doesn't need that, but it's useful to me.
     
  11. huxley

    huxley

    Joined:
    Apr 27, 2009
    Posts:
    334
    Both methods appear very useful. Thanks for posting them.
     
  12. stunriver

    stunriver

    Joined:
    Mar 5, 2010
    Posts:
    10
    yeah thanks everyone for helping
     
  13. Joel-Santos

    Joel-Santos

    Joined:
    Feb 23, 2010
    Posts:
    121
    Eric5h5, can you explain better what you did here?
     
  14. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    I might be able to help you out here ;-)

    Most of the shaders in the Transparent section of the menu use the texture's alpha channel to create variable transparency in the image. The shaders under Transparent/Cutoff work a bit differently. They compare each pixel's alpha value with an overall cutoff threshold value. Any pixel with alpha below that threshold is not rendered at all. The point of this is that you can vary the cutoff value from a script and make different parts of the image appear selectively.

    In Eric's example, the circle contains a gradient which varies smoothly from 100% down to near zero alpha. As the cutoff value is reduced, more of the circle will appear and the revealed portion will seem to move around the circle.
     
  15. Ony

    Ony

    Joined:
    Apr 26, 2009
    Posts:
    1,977
    I'm using Eric's style and it works awesome, but...

    The problem I'm having with it at the moment is that because the material that gets its alpha altered has to be on an object, I am using a plane with the material set on it.

    In front of that plane in my GUI is the texture that surrounds the meter (like the metal ring in Eric's post). So far, so good, and it works great in the resolution I set it at.

    When I change resolutions though, the object size changes (to the new aspect ratio) and the health meter then ends up at the wrong scale. My "ring around" texture scales fine because it's in an OnGUI, but the meter objects don't.

    So, I'm trying to figure out how to properly scale them to fit directly under their "ring around" GUI textures at whatever resolution someone chooses.

    Maybe I'm going about things the wrong way, not sure. Just want to throw it out there in case anyone has a quick solution that I am probably not thinking of.

    At any rate, thanks Eric for the idea. It does exactly what I need for our meters.
     
  16. Guru

    Guru

    Joined:
    Apr 30, 2010
    Posts:
    118
    I ran into the same issue...my first thought is is scale the plane accordingly depending on the resolution. How does the GUI go about it? It's easy enough to get the resolution that it's set at but no scaling of the plane I have attempted has came out right.

    Anyone have any suggestion on how to scale a gameobject based on resolution like the GUITexture does?
     
  17. Ony

    Ony

    Joined:
    Apr 26, 2009
    Posts:
    1,977
    Yep, I'm under the gun right now and have to finish this up so I think I'm going to have to scrap using this method and come up with something else that does the same thing but without the scaling issues. Hopefully someone has a work-around.
     
  18. Renatodep

    Renatodep

    Joined:
    Mar 10, 2010
    Posts:
    11
    Hi guys,

    Ok if you do the array of lets say 100 images to make the health meter, but you start at level 1. When you reach level 2, your max health increases to 110. How would you do that using this array images method?
     
  19. Aiursrage2k

    Aiursrage2k

    Joined:
    Nov 1, 2009
    Posts:
    4,835
    I did it another way so I thought I would share it.

    Requires Unity Pro.

    Okay all you do is render nothing into a render-texture. Using this image effect.

    All you have to do after that is simply do a drawTexture using RT as your texture.


    You can obviously set the render Texture dimensions (even 256 x 256) is not that bad.


    The script.
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. [ExecuteInEditMode]
    4.  
    5. [AddComponentMenu("Image Effects/HealthCircle")]
    6. public class HealthCircleEffect : ImageEffectBase {
    7.     public float radius = 0.5f;
    8.     public Color colorGood;
    9.     public Color colorBad;
    10.     public float health = 0.5f;
    11.    
    12.     public Texture rampTexture;
    13.     public float    m_angle = 0.2f;
    14.    
    15.     void Start()
    16.     {
    17.         setHealth( health );
    18.     }
    19.     //we except health to be from 0 to 1.
    20.     public void setHealth(float health)
    21.     {
    22.         m_angle = health * 360f;
    23.     }
    24.     void OnRenderImage (RenderTexture source, RenderTexture destination) {
    25.         material.SetColor("m_colorGood",colorGood);
    26.         material.SetColor("m_colorBad",colorBad);
    27.         material.SetFloat("m_angle",m_angle);
    28.         material.SetFloat("m_radius", radius);
    29.         material.SetTexture("rampTexture",rampTexture);
    30.         Graphics.Blit (source, destination, material);
    31.     }
    32. }
    33.  
    Shader
    Code (csharp):
    1.  
    2. Shader "Hidden/SphereEffectX" {
    3. Properties {
    4.     _MainTex ("Base (RGB)", RECT) = "white" {}
    5.     rampTexture ("Base (RGB)", 2D) = "rampTexture" {}
    6. }
    7.  
    8. SubShader {
    9.     Pass {
    10.         ZTest Always Cull Off ZWrite Off
    11.         Fog { Mode off }
    12.                
    13. CGPROGRAM
    14. #pragma vertex vert_img
    15. #pragma fragment frag
    16. #pragma fragmentoption ARB_precision_hint_fastest
    17. #include "UnityCG.cginc"
    18.  
    19. uniform samplerRECT _MainTex;
    20. uniform sampler2D rampTexture;
    21. uniform float _RampOffset;
    22. uniform float m_angle = 0;
    23. uniform float m_radius = .5;
    24. uniform float4 m_colorGood = float4(1,1,0,1);
    25. uniform float4 m_colorBad   = float4(1,0,0,1);
    26. float4 frag (v2f_img i) : COLOR
    27. {
    28.     float4 rc = float4(1,0,0,0);
    29.     float2 distance = i.uv - float2(0.5,0.5);
    30.     float d = length(distance);
    31.     float rad = atan2(distance.y,distance.x);
    32.    
    33.     if(rad < 0)
    34.     {
    35.         rad += (3.14 * 2);
    36.     }
    37.     float angle = (rad * 180) / 3.14;
    38.     if(d < m_radius)
    39.     {
    40.         rc = m_colorGood;
    41.         if(angle > m_angle)
    42.         {
    43.             rc = m_colorBad;
    44.         }
    45.     }
    46.     return rc *tex2D(rampTexture, i.uv);
    47. }
    48. ENDCG
    49.  
    50.     }
    51. }
    52.  
    53. Fallback off
    54.  
    55. }
    56.  
    [/code]

    attached a screenshot
     

    Attached Files:

  20. Alesk

    Alesk

    Joined:
    Jul 15, 2010
    Posts:
    340
    The "best" solution to get a non linear health bar, in my opinion, is to build a mesh having the shape needed, and then change the UV coords in real time to define what is visible on the bar.
    Then you'll only need to store a simple linear texture, and not be bothered with alpha stuff
     
  21. roguehallow

    roguehallow

    Joined:
    Oct 7, 2010
    Posts:
    3
    Hi folks. Sorry if I'm beating a dead thread here, but I'm having some issues related to alpha channels.

    For the record, I am using GIMP for my image editing.

    I'm trying to implement Proton and Eric5h5's suggestion: scaling the alpha cutoff value through scripts to grow and shrink a circular life bar. I have the diffuse life bar graphic, which goes from green to red, and the alpha graphic, which goes from black to white. They are in a .psd file, though I can save to basically any format (.jpg, .bmp, .tiff, .trg, .png, etc.).

    When I leave the diffuse and alpha as separate layers, GIMP refuses to export them until they are flattened or merged. When I turn the alpha graphic into the diffuse layer's alpha channel using a layer mask, then import the image to Unity (in any format), in the Inspector the image's alpha shows up as a solid white circle instead of the gradation from black to white that I had intended. In fact, that happens even if I merge or flatten the image. No matter what, the life bar alpha is always solid white instead of graded.

    Does anyone know how to add the graded alpha to the diffuse graphic, and have it show up as such in Unity? Thanks in advance for any help or advice.

    RH
     
    Last edited: Oct 7, 2010
  22. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Welcome to the forum, roguehallow!

    The layer mask won't affect the alpha channel of the image directly. Starting with the original image, use the Layer > Transparency > Add Alpha Channel command (or use it from the contextual menu). As you might expect, this will add an alpha channel to the image and you can access it from the Channels panel. With the alpha channel selected, you can just draw into it in greyscale with the usual tools.
     
  23. roguehallow

    roguehallow

    Joined:
    Oct 7, 2010
    Posts:
    3
    Thanks andeeee!

    UPDATE:
    It's looking much better now. I imported the image as a .png instead of a .psd and that brought back the green. I'm still fighting some ugly artifacts around the edges, but for all intents and purposes, it's working!


    Old Post:
    It's working - sort of. The good news is that changing the cutoff value raises and lowers the player's health as I had hoped. But it looks darn ugly. Here's where I'm at:

    I made a layer mask for my green-to-red health meter and pasted my alpha image into it. I then applied the layer mask, thus turning my health bar's alpha from white to graded black-to-white.

    When I do this, the main green-to-red health bar image becomes transparent, so that the red shows strongly but the green fades out. When I import the image to Unity and test it in-game, the part of the health bar that should be green is white. I also get those nasty white artifacts around the edges.

    Is there a way to make the main green-to-red image maintain its full alpha, while still having the graded alpha channel? Also, I wonder if important a different file format (.png, .trg, etc.) would be better than a .psd?

    Thanks again!

    RH
     
    Last edited: Oct 7, 2010
  24. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    How are you drawing the red/green graphic? If you are using an object with one of the Transparent/Cutout shaders on its material then the alpha should be all or nothing depending on the cutoff value. Are you also overlaying the same graphic with GUI.DrawTexture or anything like that? Perhaps you could post your code to show what you are doing.
     
  25. bryanleister

    bryanleister

    Joined:
    Apr 28, 2009
    Posts:
    130
    Thanks everyone for the suggestions, I too wanted to make a circular health-type indicator that would be scriptable. I like the gradient idea, but I couldn't get rid of a ragged edge where the bar ended. I also wanted to make my bar semi-transparent and the cut-off shaders don't seem to allow that.

    The technique that I used was to create a vertical texture, with the top half of the alpha white, and the bottom half black. I then created a circle polygon shape that has the UV's oriented so that the texture wraps in a circular manner. This shape actually works nice with the a vertical gradient and the cut-off shader like the example posted earlier.

    For my example, I have tiled the texture .5 on the Y axis and I can then script the Y offset from 0 to .5. The shader I'm using allows an alpha in the color channel so I can also make it semi-transparent. I'll attach it if anyone is interested.

    I still don't think I can use this though, my plan was to have 100's of these indicators in a scene and it looks like I would have to create hundreds of unique copies of the texture. I think it would be more efficient to create something like this through geometry so that I can control each shape individually.

    Project is attached.
     

    Attached Files:

  26. theinfomercial

    theinfomercial

    Joined:
    Sep 9, 2008
    Posts:
    1,000
    I have this problem too, and it sucks.

    When the cutoff value is near zero, the bar looks nice. But when the cutoff value is near one, the alpha looks like it's been nibbled at the edges.

    See screens:

    $1.jpg $2.jpg

    Is there a way to fix this? How did you fix it, Eric (or did you)?
     
  27. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    The gradient tool of graphics software often has a dither/jitter option to mix pixels of slightly different shades to avoid a "banding" effect. However, this will tend to create the ragged edge effect with the alpha cutoff technique. Try creating the gradient with dithering turned off if your software has this option.
     
  28. theinfomercial

    theinfomercial

    Joined:
    Sep 9, 2008
    Posts:
    1,000
    No, that made the effect even worse. :(

    Is it possible to even get smooth results with alpha cutout this way?
     
  29. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You can use the gradient texture that I posted on page 1. I turned off dithering so it wouldn't get ragged edges. The only downside is that there's no anti-aliasing.

    --Eric
     
  30. theinfomercial

    theinfomercial

    Joined:
    Sep 9, 2008
    Posts:
    1,000
    That's the thing. I used your texture first originally. But it still had problems with alpha eating (like the images pictured above in my previous post). Did you use some kind of shader?
     
  31. theinfomercial

    theinfomercial

    Joined:
    Sep 9, 2008
    Posts:
    1,000
    I hate to bump this, but I really need to know why Eric's health bar in his webplayer works and mine doesn't. Is it a shader? A certain implementation?
     
  32. Mid

    Mid

    Joined:
    Nov 3, 2009
    Posts:
    27
    Hi, I was having the same problem, playing with gradient options in photoshop, didn't help, and i was managed to get gradient without jitter in GIMP. So now it looks nice. Try GIMP.
     
  33. Robbilie2

    Robbilie2

    Joined:
    Aug 4, 2010
    Posts:
    262
    hey guys im tryin somezhing like this too and would like to use eric5h5 s idea but i cant get it to work :(

    can anybody post a small unitypackage or a detailed step by step?

    Thanks

    PS: would that be possible to use for other shapes than a circle like only a box or an oval egg?
     
  34. Mid

    Mid

    Joined:
    Nov 3, 2009
    Posts:
    27
    Here it is. And yes, you can use any shape.
     

    Attached Files:

  35. Robbilie2

    Robbilie2

    Joined:
    Aug 4, 2010
    Posts:
    262
    thanks mid ;)
     
  36. cemC

    cemC

    Joined:
    Dec 23, 2010
    Posts:
    214
    Thhanks Mid. But i mention that how can i make HealthBar by using this logic?
     
  37. theinfomercial

    theinfomercial

    Joined:
    Sep 9, 2008
    Posts:
    1,000
    Just thought I'd mention that I was finally able to get the health bar working without any artifacts. The trick is to hide the edges of the bar behind a foreground object. Like so:

    $2.jpg

    $3.jpg

    $1.jpg
     
    Mondole and rakkarage like this.
  38. Kotzu

    Kotzu

    Joined:
    Dec 26, 2010
    Posts:
    41
    Looks perfect :) Are u going to release it? :) I love the looks ! it's so SF LD
     
  39. theinfomercial

    theinfomercial

    Joined:
    Sep 9, 2008
    Posts:
    1,000
    It's what?

    I don't plan on releasing it since that health bar will be used in my IOS game
     
  40. Kotzu

    Kotzu

    Joined:
    Dec 26, 2010
    Posts:
    41
    SF LD = Science Fiction :D

    misstyped :)) sorry,
     
  41. AndrewGrayGames

    AndrewGrayGames

    Joined:
    Nov 19, 2009
    Posts:
    3,821
    This is a problem I'm trying to tackle in a fresh way.

    I have a graphics library, in it is this lovely class:

    Code (csharp):
    1. class meterOnGUI
    2. {
    3.   var position : Vector2;
    4.   var target : Vector2;
    5.   var meterOffset : Vector2;
    6.   var base : Texture2D;
    7.   var meter : Texture2D;
    8.   var meterMask : Texture2D;
    9.   var tint : Color;
    10.   var targetTint : Color;
    11.   var drawHorizontal : boolean = true;
    12.   var layer : int;
    13.   var tweenSpeed : float;
    14.   var fraction : float;
    15.  
    16.   private var tempMeter : Texture2D;
    17.  
    18.   function DrawMe() : void
    19.   {
    20.     if( ! base || ! meter ) { return; }
    21.    
    22.     GUI.depth = layer;
    23.     GUI.color = tint;
    24.    
    25.     GUI.DrawTexture( Rect( position.x,position.y, base.width,base.height ), base );
    26.     if( drawHorizontal )
    27.     {
    28.       GUI.DrawTexture( Rect( position.x+meterOffset.x,position.y+meterOffset.y, meter.width*fraction,meter.height ), meter );
    29.     }
    30.     else
    31.     {
    32.       GUI.DrawTexture( Rect( position.x+meterOffset.x,position.y+meterOffset.y, meter.width,meter.height*fraction ), meter );
    33.     }
    34.   }
    35.  
    36.   function Tween() : void
    37.   {
    38.     if( position != target )
    39.     {
    40.       position = Vector2.Lerp( position, target, tweenSpeed );
    41.     }
    42.    
    43.     if( tint != targetTint )
    44.     {
    45.       tint = Color.Lerp( tint, targetTint, tweenSpeed );
    46.     }
    47.   }
    48. }
    I'm trying to make it such that, instead of stretching the "meter" Texture with the resulting ugly-as-heck effect, instead I just render the meter texture with the alpha value of the pixels from the meterMask texture.

    In other words, the definition of an alpha mask.
     
  42. jorgenegreiros

    jorgenegreiros

    Joined:
    Jul 30, 2011
    Posts:
    95
    Hello everybody .... Can someone help me make this bar to be loaded from the bottom up.

    because I can only do it to be loaded from top to bottom.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class PowerBar: MonoBehaviour {
    5.    
    6.     public float barDisplay ;
    7.     public Vector2 pos = new Vector2(20,40);
    8.     public Vector2 size = new Vector2(60,20);
    9.     public Texture2D emptyTex;
    10.     public Texture2D fullTex;
    11.     public float speeDisplay=0.0f;
    12.     public bool DirectionUp;
    13.     public GUIStyle style;
    14.    
    15.     public static float outPower;
    16.     void OnGUI() {
    17.      
    18.         GUI.BeginGroup(new Rect(pos.x, pos.y, size.x, size.y));
    19.         GUI.Box(new Rect(1,0, size.x, size.y), emptyTex,style);
    20.  
    21.        
    22.         GUI.BeginGroup(new Rect(0,0, size.x , size.y* barDisplay));
    23.         GUI.Box(new Rect(1,0, size.x, size.y), fullTex,style);
    24.        
    25.         GUI.EndGroup();
    26.         GUI.EndGroup();
    27.     }
    28.  
    29.     void Update() {
    30.        
    31.         if(barDisplay<=0)
    32.             DirectionUp= true;
    33.            
    34.             if(barDisplay>=1)
    35.                 DirectionUp=false;
    36.                
    37.                 if(DirectionUp)
    38.                 {
    39.                     barDisplay += Time.deltaTime*speeDisplay;
    40.                
    41.                 }else{
    42.                             barDisplay -= Time.deltaTime*speeDisplay;
    43.                         }
    44.        
    45.                     if(barDisplay>0)
    46.                         outPower = barDisplay*1000;
    47.                         print(outPower);
    48.                    
    49.     }
    50.    
    51. }
     
  43. sssoul

    sssoul

    Joined:
    Oct 27, 2010
    Posts:
    3
    TT Plz sample project TT
     
  44. sssoul

    sssoul

    Joined:
    Oct 27, 2010
    Posts:
    3
    plz sample project TT
     
  45. meeshoo

    meeshoo

    Joined:
    Jan 26, 2012
    Posts:
    15
    Hi, I'm new to the forum, but not so new to Unity. I worked quite a few days to get this effect right and I'll be using it in my game, Wisps: The Redeeming.

    First, the jagged borders are not only because of dithering/no dithering, but you also have a problem if you let Unity to put any kind of filtering on that alpha map texture. Bilinear filtering will produce some grey pixels there that will give you quite a headache, so use Point filtering on the texture, but then you have to be careful when resizing the plane that uses it.

    In my case I wanted also a "trail" effect, so the moving bar is not so clearly "cut" from the background, but has a trail in which the foreground and background colors are blended. I wrote a surface shader for this that allows you to specify the gradient, two color textures (one's alpha channel is also used for the gradient), one for the moving part and one for the remaining background and two colors for tinting the two color textures. You can set a trail size, and a cutoff that goes between [-1:1] but it is useful only between [-Trail:1]. It sounds complicated, but if you try and use it, you will see what I mean. Here is the source code, hope it helps.

    Cheers!


    Code (csharp):
    1. Shader "JungleTroll/ProgressBar"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("Main Color", Color) = (1,1,1,1)
    6.         _SecondaryColor ("Secondary Color", Color) = (1,1,1,1)
    7.         _MainTex ("Main (RGB) Trans (A)", 2D) = "white" {}
    8.         _SecondaryTex ("Secondary (RGB)", 2D) = "white" {}
    9.         _CutOff ("Cutoff", Range (-1, 1)) = 0.5
    10.         _TrailFactor ("Trail", Range (0, 1)) = 0.05
    11.     }
    12.  
    13.     SubShader
    14.     {
    15.         Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
    16.         LOD 200
    17.  
    18.         CGPROGRAM
    19.         #pragma surface surf Lambert alpha
    20.    
    21.         sampler2D _MainTex;
    22.         sampler2D _SecondaryTex;
    23.         fixed4 _Color;
    24.         fixed4 _SecondaryColor;
    25.         fixed _CutOff;
    26.         fixed _TrailFactor;
    27.    
    28.         struct Input
    29.         {
    30.             float2 uv_MainTex;
    31.             float2 uv_SecondaryTex;
    32.         };
    33.    
    34.         void surf (Input IN, inout SurfaceOutput o)
    35.         {
    36.             //get color from texture
    37.             fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    38.             fixed4 s = tex2D(_SecondaryTex, IN.uv_SecondaryTex) * _SecondaryColor;
    39.             //transfer alpha
    40.             o.Alpha = 1;
    41.             //get gradient size
    42.             fixed trail = _CutOff + _TrailFactor <= 1 ? _CutOff + _TrailFactor : 1;
    43.            
    44.             if(c.a > trail)
    45.             {
    46.                 o.Albedo = c.rgb;
    47.             }
    48.             else if (c.a < _CutOff)
    49.             {
    50.                 o.Albedo = s.rgb;
    51.             }
    52.             else
    53.             {
    54.                 float factor = lerp(0, 1, (c.a - _CutOff) / _TrailFactor);
    55.                 o.Albedo = factor * c.rgb + (1 - factor) * s.rgb;  
    56.             }  
    57.         }
    58.        
    59.         ENDCG
    60.     }
    61.    
    62.     Fallback "Transparent/VertexLit"
    63. }
    64.  
     
    Last edited: Apr 18, 2012
  46. Essential

    Essential

    Joined:
    Sep 8, 2011
    Posts:
    265
    Okay, after some playing around I've come up with a semi-solution to this…

    When you create your 0-100 transparency circle in your image editor (btw, to turn a gradient into a circle, use Distort>Polar Coordinates), do not actually make a 0-100 gradient, use a 50-100 gradient. That way the edge of the circle will stay clean because the circle will be completed long before the outer distortion appears.

    However, the reason this is a semi solution is because it still seems to show the ugly distortion on the flat edge when it's growing or shrinking as a circle. Dunno how to fix that. But it looks much better.
     
    Last edited: Apr 29, 2012
  47. meeshoo

    meeshoo

    Joined:
    Jan 26, 2012
    Posts:
    15
    I think you should post a screen about it to show exactly where it is distorted, but if it is where I think it is, the fix is in my previous post at the beginning: what filtering are you using when importing the texture containing the gradient?
     
  48. Essential

    Essential

    Joined:
    Sep 8, 2011
    Posts:
    265
    I tried changing to point filtering but didn't seem to make much difference… if anything, it made it look slightly worse. Here's a screenshot:



    You can see the wobbling along the edge. I put a ring texture on top that hides the distortion at the very outer edge, but the wobbling is still present.

    Here's the file if you wanted to play around: http://www.2shared.com/photo/OguBLDkz/CircleTimer.html
     
  49. meeshoo

    meeshoo

    Joined:
    Jan 26, 2012
    Posts:
    15
    If you are using an "AlphaCut" shader (like the original ideas from this thread suggested) then your texture is not good, as your alpha channel is anti-aliased around the edges, and it is very tricky to set a cutoff value that will give what you want, so you will have to turn off anti-aliasing for the gradient tool. However, that won't solve you your rough edge going from the center of the disk towards the edge. One way to improve this(still not perfect) would be to increase the resolution of the texture to around 1024, but not even that would guarantee a clear line there.

    On the other side you could use the shader I pasted, which does use alpha cut only if the alpha map has pure black on a pixel, but for all other values (255 values) it uses alpha blending, so no more jagged lines at all. I am not at home right now, but I could post a picture with the result in the evening (GMT + 2 here). Or you could just pick it up and try to use it :)
     
  50. Essential

    Essential

    Joined:
    Sep 8, 2011
    Posts:
    265
    Thanks for the info, meeshoo :)