Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Advice wanted - healthbars

Discussion in 'Entity Component System' started by bugfinders, Apr 24, 2020.

  1. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814
    I really want health bars for my mobs, previously ive only used sliders because well, they are so good at it..

    I looked into the AddHybridComponent and, it doesnt seem to like UI.. so, how is a girl to achieve a simple health bar that can follow the entity and not be really overly complicated?
     
  2. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,655
    Well I solved it by system which collects objects positions (in screen space float2) and bar parameters (blobs) per different parameters. And sends them to post processing shader. And wrote post processing effect for drawing them.
    Here is example how it looks (old videos)
    (on Alt press I'm showing them. Also I using them for building upgrades)

     
  3. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814
    Well, @eizenhorn, as always hats off to you, you do have l33t skills there. I couldnt make a shader if you set me on fire. However, you are the only one I know whos made decent health bars.
     
  4. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,993
    The post-processing effect is a good solution (I think). But if you don't want to hack into the rendering pipeline, there's a couple of things you can do.

    Probably the easiest approach is to generate a quad the shape of the full health bar whose origin is set to the left-hand side. Run a system that makes all these quads align with the camera direction and the camera's up direction. Then apply a NonUniformScale to represent the different health values. Lastly, you can also calculate an additional scale factor to compensate for perspective if desired.
     
    lclemens, florianhanke and bugfinders like this.
  5. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814

    thanks - you set me down a path and it looks like I might make it...
     
  6. wg-siggig

    wg-siggig

    Joined:
    Mar 17, 2020
    Posts:
    36
    florianhanke likes this.
  7. wg-siggig

    wg-siggig

    Joined:
    Mar 17, 2020
    Posts:
    36
    Here is my shader graph from when I last did this in ECS.

    upload_2020-4-24_20-26-46.png
     
    florianhanke likes this.
  8. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,993
    Yup. ShaderGraph instead of scaling can get you a more colorful bars. I'm not sure how good the support is for URP for Hybrid Renderer V1. But for HDRP and V2 this would probably be my goto solution if I needed to do this.
     
  9. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814

    this is where Im at I followed his thing, got a working shader (having downloaded it from github) - however, Im running into an issue where the quad isnt on the entity with the health.. so how to update that..
     
  10. destructor465

    destructor465

    Joined:
    Jan 30, 2016
    Posts:
    18
    My solution is:
    1. Create a shader to render a healthbar, should accept health value 0-1 or something. https://www.reddit.com/r/Unity3D/comments/fqtjp6/shader_based_health_bar/
    2. Each entity that needs healthbar to be displayed creates another entity with healthbar material and material block property to update health value. First entity should have reference to this entity in component.
    3. Create a system to iterate all entities with healthbar, access its healthbar entity and update position & health value in material block property component.

    Basically what wg-siggig said.
     
    Last edited: Apr 24, 2020
  11. wg-siggig

    wg-siggig

    Joined:
    Mar 17, 2020
    Posts:
    36
    You need a system that updates the position and rotation of the quads to follow those entities and align correctly to the camera.

    It's really easiest to just have this on a gameobject in your prefab and use the conversion flow.
     
  12. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814
    I dont need the quads to rotate or move, as they will move with the entity,

    My entity goes

    empty
    - many sub gameobjects that make up the tank (see unity tanks)
    - healthbar

    the empty has the health and all that jaz, the healthbar is on top (as its kinda top down) so it can rotate all it likes with the object, for now, but, what i cant work out is how to get that meshrender details from the empty part
     
  13. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814
    OK - this is clearly wrong on a lot of levels but

    Code (CSharp):
    1.        NativeArray<doit> mobs = new NativeArray<doit>(GamaDataManager.Instance.manager.CreateEntityQuery(ComponentType.ReadOnly<MobData>()).CalculateEntityCount(), Allocator.TempJob);
    2.         var i = 0;
    3.         Entities.ForEach((in MobData m) =>
    4.         {
    5.             mobs[i] =
    6.             new doit {health = (float)m.health/(float)m.Maxhealth };
    7.             i++;
    8.         }).Run();
    9.         i = 0;
    10.         Entities.WithoutBurst().ForEach((RenderMesh mr, in HealthBar h) =>
    11.         {
    12.             var mr2 = mr;
    13.             /*
    14.             mr2.GetPropertyBlock(matBlock);
    15.             matBlock.SetFloat("_Fill", mobs[i].health);
    16.             mr2.SetPropertyBlock(matBlock);*/
    17.             mr2.material.SetFloat("_Fill", mobs[i].health);
    18.             mr = mr2;
    19.             i++;
    20.         }).Run();
    21.         mobs.Dispose();
    So, I got the material but unlike the meshrenderer, you cant get the block, and so none of them change because I guess its changing the fill value for the original material not its instance??
     
  14. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,993
  15. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814
  16. wg-siggig

    wg-siggig

    Joined:
    Mar 17, 2020
    Posts:
    36
    You need to expose parameters on your shader graph and then set values on them via code.
     
  17. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814
    Believe me I tried - however _Fill is the shader not the material..

    Code (CSharp):
    1. [MaterialProperty("_Fill", MaterialPropertyFormat.Float)]
    2. public struct HealthBar : IComponentData{ public float Value; }
    with a system doing
    Code (CSharp):
    1.  
    2.         var i = 0;
    3.         Entities.ForEach((Entity e, in MobData m) =>
    4.         {
    5.             var h = (float)m.health / (float)m.Maxhealth;
    6.             mobs[i] =
    7.             new doit {e = e, health = h };
    8.             i++;
    9.         }).Run();
    10.         Entities.ForEach((ref HealthBar h, in Parent p) =>
    11.         {
    12.             var localh = h;
    13.             for (int j = 0; j < mobs.Length; j++)
    14.             {
    15.                 if (p.Value == mobs[j].e)
    16.                 {
    17.                     localh.Value = mobs[j].health;
    18.                     h = localh;
    19.                     break;
    20.                 }
    21.             }
    22.         }).Run();
    what happens? the health bar never changes but I know health is going down, and maxhealth is staying the same. PS I checked, mobs[j].health is definitely the right value.
     
    Last edited: Apr 24, 2020
  18. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,993
    Ok. So let's back up a little bit. Which version of Unity are you using? Which render pipeline are you using and which version?

    Shader graph is really easy for basic effects like this. Learning it will let you easily drive some pretty cool effects directly from DOTS.
     
  19. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814
    Im on 2020.1b6, and using the hybrid renderer 0.4.2 - and as mentioned before, i seriously dont understand shaders!
     
  20. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,993
    Which Render Pipeline? Legacy? URP? HDRP? And if URP or HDRP, which version?

    You don't need to understand shaders to understand Shader Graph.
     
  21. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814

    well im glad I dont need to understand it, cos atm, I so dont.

    Its the built in pipleine
     
    UsmanMemon likes this.
  22. brunocoimbra

    brunocoimbra

    Joined:
    Sep 2, 2015
    Posts:
    677
    Shader Graph doesn't work with built in pipeline AFAIK
     
  23. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814
    all this for a frickin crappy tower defense messin about project..

    well

    I put urp on it, (8.0.1), and shadergraph..

    I have something that if I change _fill to 0 its green and 1 its red on a texture2d node, but it currently doesnt do a swapping over type effect.. at any of the points in between. But its a start

    I tried to follow what I thought was the logic in the shader the website had made - clearly I am a fool, it was not good, however, my "main preview" stays black.. no matter what Ive tried so far.

    Im also watching
    but, as this is nothing like what i want, i fear it will lead me in ways I dont need to go
     
  24. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,993
    Shader Graph does not work with built-in, nor does Hybrid Renderer V2. So unless you are far along into your project, I suggest moving to one of the newer pipelines.

    Otherwise the scale trick is probably your only way forward given your stance on shaders.
     
  25. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,993
    Apparently I'm a little late. So I would recommend feeding the x component of the UV into a step node, with the health value (scale of 0 to 1) as your edge. Then feed that into a One Minus node.
     
  26. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814
    that sounds helpful - my project seems to be working in urp excrept the health bars but what im finding compared to brackeys is that my shader is not appearing anywhere.. so I cant seem to use it!

    I also cant seem to do what you suggested my UV has no inputs only outs, and while I can split it into 4 as it says Out4 that seemed reasonable, so I took R1 .. it only has rgba so.. no x.. put that in a step with the fill, took the out of that and -1 and .. blackness all the way.
     
    Last edited: Apr 24, 2020
  27. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814


    So I made this, as you can see the exposed property _Fill is there, and it does if I change it in the graph seemingly do sort of what i wanted.. although i kinda wanted the red/green round the other way but right now.. I'll take it

    However

    add


    Code (CSharp):
    1. [MaterialProperty("_Fill", MaterialPropertyFormat.Float)]
    2. public struct HealthBar : IComponentData{ public float Value; }
    with a system doing
    Code (CSharp):
    1.  
    2.         var i = 0;
    3.         Entities.ForEach((Entity e, in MobData m) =>
    4.         {
    5.             var h = (float)m.health / (float)m.Maxhealth;
    6.             mobs[i] =
    7.             new doit {e = e, health = h };
    8.             i++;
    9.         }).Run();
    10.         Entities.ForEach((ref HealthBar h, in Parent p) =>
    11.         {
    12.             var localh = h;
    13.             for (int j = 0; j < mobs.Length; j++)
    14.             {
    15.                 if (p.Value == mobs[j].e)
    16.                 {
    17.                     localh.Value = mobs[j].health;
    18.                     h = localh;
    19.                     break;
    20.                 }
    21.             }
    22.         }).Run();
    it doesnt change still... stays green the whole time

    if i add a counter to show the health values have changed, i get changes, if i list the values, I see the right values for health, but that _Fill aint happening for me and the workings of my shader is voodoo.. all this hassle for a simple healthbar

    PS if I move the slider by hand it seems to work.. so we must be close!
     
    Last edited: Apr 25, 2020
  28. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814
    Now I read that swapping colours/values in a material doesnt work with URP.. sigh this was only going to be a small webgl game!
     
  29. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,993
    This is what I meant with the shader graph. Note I don't even use textures for this, as in this particular case textures are unnecessary. upload_2020-4-24_19-41-42.png

    Make sure you have that Hybrid Instanced checkbox checked, and it should work with the version of Unity and URP you are using.
     
    florianhanke likes this.
  30. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814
    well i had the hybrid checked and mine didnt work even though changing _Fill by hand did.. I wish I had proper understanding as to why i got so close and it didnt work

    Well using your shader graph ive gotten somewere but now it flickers all over the place even when I know the health is static. its almost like its doing it depending on where it is in the world.
     
  31. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,993
    Without seeing it I can't help you. Are you making the quads face the camera?
     
  32. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814
    nope. they point "up" as the camera is up and rotate with the tanks..

    upload_2020-4-25_3-21-7.png

    Given the fill colour is 0,255,0,255 and the empty is 255,0,0,255 .. how do you get yellow, green, cyan and black out of all that? It flashes different colours as you move the mouse around and stuff while paused too.. as you can see, it truly is an epicly naff game and really not worthy of such effort, but if i can get my head round why and how I will be much better off in the long run - oh and every last one of those is at full health....
     
  33. jdtec

    jdtec

    Joined:
    Oct 25, 2017
    Posts:
    299
    I just used standard Unity UI to make a health bar prefab on a canvas.

    Then I update the healthbar monobehaviour properties using the relevant component values. Incredibly straight-forward and full artist control for the health bar appearance.

    Code (CSharp):
    1. float2 screenPosition = m_entityManager.GetComponentData<ScreenPosition>(m_entity).Value;
    2.  
    3. m_frameTransform.position = new float3 (screenPosition.x, screenPosition.y + HealthBarOffsetY, 0.0f);
    4.  
    5. float health = m_entityManager.GetComponentData<Sim.Health>(m_entity).m_health;
    6. float maxHealth = m_entityManager.GetComponentData<Sim.HealthProperties>(m_entity).m_maxHealth;
    7.  
    8. float healthPercentage = health / maxHealth;
    9. m_barTransform.localScale = new float3 (healthPercentage, 1.0f, 1.0f);
     
  34. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814
    Interesting - how do you detect when to remove the healthbar, does having so many UI elements being updated slow down your game much?

    for everyone else

    Interestingly using the shader @DreamingImLatios showed, and having removed all health altering code, the healthbars still flash random multi colours not just the red/green

    I feel like Im missing one link in the chain, that it will all work if only i had it.. Yesterday at least I had at one point the healthbars working but only when the last entity was effected now i cant even seem to make that.. it puzzles me as even when the game is paused the healthbars are randomly changing colour as your mouse moves about

    to show you what i mean, this is the game - clearly paused with just me waving the mouse about

     
  35. Bivens32

    Bivens32

    Joined:
    Jul 8, 2013
    Posts:
    36
    Did you upgrade URP to version 9? I'm not sure it shows up in the package manager ui yet. I don't think the shadergraph properties work from an IComponentData property with version 8.
     
  36. jdtec

    jdtec

    Joined:
    Oct 25, 2017
    Posts:
    299
    No not really. If you have hundreds to thousands of units it might start to be an issue.

    I run unit health updates at the start of the frame on the mainthread so that other systems can get the results on the same frame. I have a system using system state components to detect the unit death in a ForEach...WithoutBurst().Run() so that it can simply call monobehaviour callbacks to the health bar UI directly.

    This method won't be optimal but when you're prototyping and just want to see what something looks like before committing to it, it's nice to get it done quick and easily.

    In my case if it becomes an issue later I might change it. By the time that happens DOTs (and the other preview/immature packages mentioned here) may have better support for solving the problem anyway.

    It depends what you want but I thought I'd mention this incase it matches your situation more.
     
    bugfinders likes this.
  37. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814
    No, no I havent.. but what i am concerned with is even without changing any values Im getting weird effects. what happens if I try and change the values - trying it... nope Im still seeing the weird random colours ..


    Obviously its more like what im used to, but the idea of keeping track of the entity and moving the bar seems also superfluous,
     
    Last edited: Apr 25, 2020
  38. bugfinders

    bugfinders

    Joined:
    Jul 5, 2018
    Posts:
    814
    @DreamingImLatios is a hero

    It now works

    what was mainly wrong??? I had actually done (at one point) all the right things bar one stupid dumb bit. When I named my parameters, I named it _Fill .... I didnt realise the "reference" underneath it was what it was looking for.

    It also seems that _Fill is a bad reference name for it.. it doesnt complain but changing it to "turkey" and restarting unity ... suddenly I have working healthbars!!!
    whoohoo
     
    brunocoimbra likes this.