I'm struggling to create a circular bar with an animated texture and a round cap end. What I would like to create is implemented in the Unity game Subnautica - the bottom left bar. So here is the HUD from the game. The problem is that I don't know how to animate texture with the round end. I can fake it with basic colors but I need it to have animated texture.It is possible to make this using shader because i hadn't tried that. Or are there maybe some assets in the store?
2 Answers
Going to plug my $2 shader asset, its not required to get this to work, but it will look better (this is due to alpha cutoff works).
Step 1: make your texture.
Your texture will need to have the circular graphic you want to display and then you need to fiddle with the alpha so that it has the curved feature you want. I'm going to spend no more than 10 minutes trying to do this, so results may not be perfect.
You want it so that the low end of your bar is 100% opaque and the high end (the 100% full portion) to be 1% opaque (almost completely invisible). Not fully transparent, as you still want there to be bits available for the portions of the texture you won't be using at all.
Something that looks like this on the alpha:
This wasn't perfect, the first third of the bar is perfectly white (limits of the tool I was using), but it gives you the right idea.
Then the final image will look like this:
The curved portion of the bar as it fills in isn't 100% accurate here either, but I did say no more than 10 minutes.
You will also want a background texture that will display behind (and around) the bar. I'm going to skip that for this example.
Step 2: set up your material
Create a material, assign your texture, set the shader to Unlit -> Transparent Cutout, add a quad to your scene with the material applied.
You may also be able to use it as a UI sprite material, I haven't fiddled around with those much because the shaders tend to vomit errors when they don't have some settings that the UI expects. I think I fixed it completely once, here. The six [HideInInspector]
lines and the Stencil
block are what need to be added to make a shader work properly on UI components. Should work for any shader, though I've not tested extensively. Unity built-in shaders (e.g. AlphaCutout) can be downloaded in the archive, just change the dropdown from "Downloads" to "Built-in Shaders."
Step 3: profit
You're done!
My alpha shaders will make those ugly jaggies go away by blurring the edges slightly (configurable, I suggest small values of around 0.02) and then some care regarding the setup of the alpha channel and you can get some pretty good results. Asset is $2 because I can't make it $1, if you know what you're doing you can recreate the shaders in a half hour or so (and if you don't, that's why it's $2 ;). Layer a mask on top (link is for UI sprites) and you can constrain the filled part's edges even better.
It probably won't be 100% to Subnautica's bar, as it has an outline applied that this method can't replicate, but you can get something pretty close for almost no work.
This question inspired me to go back to my shader asset and add two new textures for circular progress bars, including a much refined version of what you're looking for (the leading edge is much more circular). The entire process of creating the correct and accurate alpha composite took about 3 hours. Here's the end result (with blend range of 0.03 so you can see some of the progression). Note that the black border is a second texture giving the bar a background to sit inside.
In the Unity documentation there is an Image.Type.Filled component. The description says:
Displays only a portion of the Image.
A Filled Image will display a section of the Sprite, with the rest of the RectTransform left transparent. The Image.fillAmount determines how much of the Image to show, and Image.fillMethod controls the shape in which the Image will be cut.
This can be used for example to display circular or linear status information such as timers, health bars, and loading bars.
See Also: Image.FillMethod, Image.fillAmount, Image.fillOrigin.
-
2\$\begingroup\$ Note that this will produce a straight cut-off, rather than the rounded ends as shown in the question. \$\endgroup\$– DMGregory ♦Commented Sep 8, 2018 at 11:34