I’ve been coding since 2019, and it took 2 years, 2021, until my programming skills got good enough to where I could make my own games instead of slightly tweaking free models or using tutorials. I wouldn’t call this tutorial hell, rather, I was having so much fun doing these basic things, that I never had enough motivation to learn how to actually code. In Jan 2, 2021, I wanted to remake my first game, made on that very same day in 2018. What I did to “learn” was to take free models and tutorials, and to use them in my games. What I was doing differently this this was trying to understand what I was looking and using those free models or tutorials or whatever to make something new. Like I would take script from a tycoon free model that added a Cash leaderstat to your game, and I changed it to add a Gold and a Shards leaderstat instead. I did this over numerous projects, until I FINALLY knew what I was doing in late 2021. And for a solid year straight, I worked on tiny projects that isolated individual features until I knew enough to make a larger project, which I would then quit a few weeks after starting it because I wasn’t good enough, starting the whole cycle over and over again. This lasted until 2023, where in the last 5 months of the year I got insanely good at programming by studying theory and proper code-base design and a lot of nerdy stuff.
Moral of the story: If you’re having fun, and trying new things, you’ll eventually learn how to code after enough time.
If there was only one piece of wisdom I could share about learning to code, it would be this:
Don’t try to wander off and work on stuff without outside help when you are a beginner. That is something that only seriously advanced developers can do. You will miss out on a lot of key knowledge, and in the process, you’ll spend too much time working on trying to get stuff to work, that you’ll get bored of working on the project, or even coding itself if you do this too much. When you’re learning, or doing anything really, you want to see results fast, which will encourage your mind to continue working on something, even if you’re maybe not putting in all the effort you could, or maybe you’re not learning enough. As long as you don’t want to quit, you’re doing something right.
If you want some tips or advice, I’ll give you some good information on loops:
Let’s say you have a TextLabel that you want to display the player’s current health at all times. You could do this by having an infinite loop constantly changing the label’s text to the players current health.
while task.wait() do
script.Parent.Text = game.Players.LocalPlayer.Character.Humanoid.Health
end
That line of code that changes the TextLabel’s Text is quite scary, and that’s one of the big issues with programming with game engine, since you need to know a lot of stuff before you can make anything substantial.
Breakdown:
A while loop is comprised of three elements:
- A Condition
- A Code block
- An End statement
For the condition element of a while loop, you write it like this:
local condition = true --// Can also be false
while condition do
end
It checks if the condition is NOT false or NOT nil, and if it is, then it runs the code block.
Once it reaches the end of the code block, which is written as simple end, it will loop back to the start of the while loop, checking if the condition isn’t false nor nil, and then running the code block inside of it.
So a script like this:
while true do
print("Loop!")
end
Will print out “Loop!” forever.
Now, looking back at the script I showed previously:
while task.wait() do
script.Parent.Text = game.Players.LocalPlayer.Character.Humanoid.Health
end
The condition for the while loop if task.wait(), which is a function. Let’s look at its return value.
print(task.wait(1))
This script will print out the number like 1.25 or 1.674, something like that. It returns the amount of time (in seconds) that the wait lasted. Note that you should always use task.wait() over wait(), for a thousands reasons that I won’t get into, but just use task.wait() and not wait(). As you can probably tell, 1.(something) is definitely not false nor nil, so the loop runs. Thing is, whenever the condition is checked, it runs the task.wait() function. Since we are not passing any arguments throughs, aka there being nothing between the ( and ), the function waits approximately one frame.
Next is this line of code:
script.Parent.Text = game.Players.LocalPlayer.Character.Humanoid.Health
It’s definitely quite big, very simple in nature. In order for this line of code to work, this script should be a LocalScript inside of a TextLabel.
script.Parent.Text gets the Parent of the script (which should be a TextLabel), and then gets its Text. = game.Players.LocalPlayer.Character.Humanoid.Health then sets the Text to the player’s current Health. How it does this isn’t the most complicated, but I’ll give an explanation nonetheless.
game.Players is a instance that contains all players in the current Server. .LocalPlayer is the Local Player, or just the current player in other words. the GUI for each player is rendered separately from one another. Since you want each player to display their own health values, and not anyone else’s, this is great since it allows for each player to have a different value on their screens. Thing is, we need which player is currently rendering the GUI, and to do that, we need to use LocalPlayer. This only works inside of LocalScripts, which is why we’re using one. Finally, .Character.Humanoid.Health should be pretty self explanitory. Players in Roblox are represented as both a Player object inside of game.Players and a Model inside of workspace. The Player’s Health (which is inside of their Humanoid) is inside of the Model in workspace, also know as the player’s Character. So we do .Character.Humanoid.Health to get the Health of the player.
Finally, we end the script with an end to denote the end of the loop.
So here’s the script again:
while task.wait() do
script.Parent.Text = game.Players.LocalPlayer.Character.Humanoid.Health
end
Every loop we wait one frame, change the TextLabel’s text to the Player’s health, and then we’ll loop over again the next frame.
All you really need to make fully fledged games is the simple while loop, but other loops, like for loops and repeat loops (and even recursion if you count that) make certain things really easy.
Take this script:
for index, instance in pairs(workspace:GetChildren()) do
print(instance)
end
This script will print out each instance inside of the workspace.
This script should be a Script inside of ServerScriptService
Let’s look at the first line.
for index, instance in pairs(workspace:GetChildren()) do
it begins with
for index, instance This declares two local variables, index and instance, which we will be using later. Next in pairs(workspace:GetChildren()) is quite simple. workspace:GetChildren() Returns a table of all of workspace’s children. So for example, if your workspace looked like this:

And we called workspace:GetChildren(), it will output a table containing every child of workspace, which would look like this:

as you can see, each row in the table consists of a pair of two values, a number value, which is called the index, and a value value, which in this case, is an instance.
When we put workspace:GetChildren() into the pairs() function, it will iterate over each row of the table you put in as the argument (workspace:GetChildren() in this case), and return a pair of two values, the index and the value.
When we do:
for index, instance in pairs(workspace:GetChildren()), we are esentially setting the index and instance variables to the index and values that the pairs function is returning.
Next, the code block. The only thing inside of it isprint(instance), which will quite obviously print out an instance inside of workspace. The end statement is the same as in the while loop as well. This loop will loop through each row of the table, until there are no more rows to go over.
Will that all being said, the script will print this:

Code:
for index, instance in pairs(workspace:GetChildren()) do
print(instance)
end
This code loops through each child of the workspace and prints that out into the output.