So I'm working on this Health GUI thingy and I'm trying to make it so that whenever the hunger value decreases, the size of the hunger bar will also decrease in that same percent of the value. The main problem is converting the number value of the hunger (200 by default) into a UDim2 X Scale value Any help or guidance is much appreciated!
local Value = script.Parent.Value local stat = script.Parent.Stat local number = script.Parent.Number local player = game.Players.LocalPlayer local Time = script.Parent.Time.Value -------------------------------------------------------------------- while (player ~= nil) do wait(Time) Value.Value = Value.Value -1 --Decrease hunger number.Text = Value.Value --Display hunger value on GUI end while (player ~= nil) do wait() Value.Value(1) == script.Parent.Size.X.Scale(0.1) --Convert hunger values end
This may seem very confusing to you, but that's okay, because you don't need to understand this to it's fullest extend yet. However, there's a fundamental aspect of this that you need to understand before we get into an answer for your question, which can best be described with context switching (you can read about that later).
Let's think about what loops do for a second. A loop will continue to execute it's body of code, until it's condition is no longer met, or until something in the loop discontinues it. Until the loop has ended, the program will not move on to the next line of code. This means if you have two loops running forever inside a program (as shown in your script), your program is only going to execute the first one it runs into. It will never reach the second loop, because the first one never ends. Just imagine trying to count past infinity.
Most of the time, you won't need multiple infinite loops at once to accomplish something. Sometimes there'll be an event you can listen for, or you can just have all your instructions running withing the same loop. However, if there is a special case where you do need some instructions to run in the "background", there is a solution. ROBLOX implements what's called a thread scheduler, along with built-in functions to manipulate it (sort of). Functions like spawn
and delay
can be used to execute code almost as if it's in a totally different script in your game. Here's an example:
-- Using spawn and passing a function for the thread scheduler to execute spawn(function() while wait(1) do print("Running loop 1") end end) -- Creating an ordinary loop that runs forever, just like the one above in the spawned function. while wait(1) do print("Running loop 2") end
If you ran this in ROBLOX, you'll notice both loops will execute their code side by side, even though they're both in the same script. You should get this pattern:
-- > Running loop 2 -- > Running loop 1 -- > Running loop 2 -- > Running loop 1 -- > ... so on
This however, is actually just an illusion. Code in your game isn't running independent of itself, even code inside a different script. Everything is being handled by ROBLOX's thread scheduler, which just takes turns executing one instruction at a time, just in different contexts. Whenever something in your program causes it to pause (or yield), even briefly, the scheduler immediately chooses the next script (or "thread") to start, or resume executing. In order to resume something however, you need to know where it left off. This can be demonstrated with the yield
function of the coroutine
library, which allows a function to pause itself, and later be resumed starting where it left off.
This is a huge concept of context switching. Allowing program A to save the current state of itself, switch over to executing instructions for program B, and then get back to where program A was. It's a bit to grasp all at once, but you can eventually get the hang of it.
Execution continuity isn't the only problem with your code. You also have a syntax error on line 17 (trying to use the equal to operator ==
to assign a value). You're also trying to call Value
as a function, along with Scale
, when these are both properties. You should focus on learning the basics of programming before trying to take on even the simplest project that you plan on distributing.
Just an FYI, this isn't exactly a problem with your code, but your loop condition (player ~= nil)
can just be simplified to true
, since you want the loop running forever, and true will always be true.
Sorry if I bored you with all of that, I know it's probably not something you expected to get into, but I felt the need to add it regardless. Anyway, you just want the percentage of your hunger value. Once you acquire the percentage, you can simply just set your hunger bar's scale to that value. The equation for getting the percentage of something, is always change or current state / maximum value
. In this case, current hunger / max hunger
. This will always return a number between 0 and 1 (0 being nothing, 1 being 100%), assuming your change is never greater than your limit.
Simply just throw that result in your size's scale, and you've got a working hunger bar perfectly in proportion to your hunger value. Here's an example:
while wait(Time) do -- Change hunger value Hunger.Value = Hunger.Value - 1 HungerBar.Size = UDim2.new(Hunger.Value/MaxHunger, 0, ScaleY, OffsetY) -- Assume you have a variable representing the full potential hunger status, and divide it by user's current hunger for X scale. Also fill in Y dimension. end
Hope that helped, if you have any questions, just let me know. I still recommend learning the basics of programming before taking on anymore tasks like this however, unless it's for personal learning experience.