Search Unity

Question How to - Unit Health bar brackets

Discussion in 'UGUI & TextMesh Pro' started by SynergiAios, Jan 4, 2023.

  1. SynergiAios

    SynergiAios

    Joined:
    Feb 3, 2015
    Posts:
    35
    As of right now, I'm trying to tackle this. I have my floating health bars and I want to add the feature of the health bar brackets/divider that you see in the screenshot. Basically what this is, it is a visual indicator of how much HP an unit has and not just how much percentage of the hp is left.



    But to be quite honest, I'm really struggling with this. Let me explain what I tried and why it didn't worked out for me.

    So the obvious first thing for me, was making a 2d sprite shader that takes care of this. But to be fair, I'm not that confident with writing shader lab code, so I use Shadergraph oder Amplify Shader Editor.
    But in both editors, I can only live with the UV Texture coordinates and can not directly work on the pixels. This yields to the situation, that drawing same thickness lines is impossible as the UV coordinates are from 0-1 or per se in percent and thus do not target the actual pixels.
    When I made the shader I hat the issue, of needing to compensate for that. And that annoys me extremely.

    Here is what I came up with shaders



    You can see the different thickness in the lines I draw. This is due to working with uv coordinates in the shader graph.

    So Okay as of right now, I have to give up on shaders. I'm not that strong with shader lab, so I can't work directly with it to write my own pixel shader that directly draws into the pixel buffer and works with pixel coordinates.

    The next thing I was thinking about, make a large texture with all the rulers on it and scale the image then according to the hp of the unit. But the issue is, if I scale the image, I have the same issue again, the thickness of the lines isn't the same.

    So as of right now, has anyone any idea to help me on how I could achieve this? It clearly has been done so it's just a question of how.

    Thx for reading and spending your time.
     
  2. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,566
    You can accomodate for line thickness within your shader. You can pass line thickness as a parameter.

    Basically, you can find position within the cell using frac .
    cellPos = frac(uv.x, cellWidth)
    . This will put values into 0..cellWidth range, where cellWidth is a parameter.

    In this window, values within (0 + lineWidth * 0.5 ... cellWidth - lineWidth*0.5) are color. Everything else can be black. This can be accomplished using step or any other function..

    Regarding texture, you'll get the same issue, and you can't do that with scaling. You can, however, prepare many different textures for different number of cells.

    Personally, I'd just fix the shader.
     
  3. SynergiAios

    SynergiAios

    Joined:
    Feb 3, 2015
    Posts:
    35
    Thanks for your time. So as of right now, I already have a width in my shader, but clearly it is wrong. Here is an Image of the shader



    Where the red arrow is, I try to compensate a width. Basically I do a modulo of the UV coordinates and then use the tolerance in compare of the remainder to be able to draw a width.

    So you are suggesting to replace this compare for what you describe. But to be quite honest, I can't follow you completely.

    Basically, you can find position within the cell using frac .
    cellPos = frac(uv.x, cellWidth)
    . This will put values into 0..cellWidth range, where cellWidth is a parameter.


    Does this mean there Is a way to calculate at which pixel I am? And also how would I count then. I have only the modulo operation as a trigger to draw a line and the compare tolerance of the remainder to know when to stop.

    If you can help me a little bit by explaining me a bit more what you mean, I would be really thankful. As of right now, I honestly can't follow you.
     
  4. SynergiAios

    SynergiAios

    Joined:
    Feb 3, 2015
    Posts:
    35
    To make actually clear what my issue is. See this picture.



    In the red circle I try to find any way to rewrite a variable on given condition. But Amplify Shader Editor blocks this, with the message "Infinite Loop Detected"

    So I'm unable to make the following
    1. Check if Module of UV Coord is in range of 0.001
    2. If yes then save that UV Coord and Add a fixed Width to it.
    3. Subtract difference of new UV Coord of fixed till 0
    4. If 0 stop drawing the line.
    Basically as I'm not able to store and rewrite any kind of flag, float or anything, I can't achieve a "FIXED" width. I tried to find a way, to have my modulo calculation as a trigger to take that UV coord, and then start a fixed drawing after this, but it is simply not possible.

    I'm not aware of shader lab and how things work, but I think there is a reason, why Amplify blocks a rewrite of a variable with infinite loop detected.

    So I'm stuck, as I can only achieve relative stripe thickness and not absolut. I will always be dependent on how accurate my Module operation triggers in what range. And if this is sometimes less accurate, the stripes thickness does differ.

    Anyone any solution to this?
     
  5. SynergiAios

    SynergiAios

    Joined:
    Feb 3, 2015
    Posts:
    35
    As of right now, I'm considering, the only way to achieve this effect, would be to threat every line as it's individual sprite and build the ruler in code by myself as in spawning in as many individual sprites for each line.

    I see no other way, if the goal is to have a persistent line thickness. I would really love to know how Dota 2 did it and like League of Legends and other games that use this dynamic ruler on their health bars.
     
  6. SynergiAios

    SynergiAios

    Joined:
    Feb 3, 2015
    Posts:
    35
    Okay I'm now committed to solving this with gameObjects. I will make cells with borders and arrange the width of them according to the amount. I think this is the only feasible way to achieve this.

    If anyone else has an Idea on how to solve this with shaders, I'm happy to hear.

    thx