Hey there. In this post I will be sharing a few common mistakes in roblox scripting.
This list isn’t in any order.
LocalPlayer and server scripts
One of if not the most common mistake. People will try to get the local player via the Players.LocalPlayer
property but get an error about attempting to index a nil value.
Think of it like this: if you told your teacher to get the local student your teacher would be very confused because who is the local student??? A player can’t be picked at random either. Code cannot read your mind. That’s why you need to type specific stuff to follow the syntax of the language.
So if you wanted to create a part in the workspace with colour red you don’t do this:
make a part in the workspace with the colour red
There are multiple ways to get the player, but in this example I’ll go over how from a Touched
event listener.
part.Touched:Connect(function(other)
local player = Players:GetPlayerFromCharacter(other.Parent);
if (player) then
-- do something with player because it's a player!!!!! :)
end
end);
:FireServer, :InvokeServer, .OnClientEvent, .OnClientInvoke; no player
Server
Lots of people assume that a reference to the local player must be passed through :FireServer
/:InvokeServer
first since that’s what is included as the first argument to your .OnServerEvent
/.OnServerInvoke
callback functions. You don’t do this since roblox does it implicitly. It wouldn’t make sense to have to do it manually either, as it could be a security issue, exploiters could fire a remote event/invoke a remote function on behalf of another player.
Changing StarterGui
over PlayerGui
You may want to make a change for all players, or for a single player. It is a common mistake to change the contents of StarterGui
over PlayerGui
. When you (re) spawn, the contents of the StarterGui
service are cloned into your PlayerGui
located under your Player
instance. The local scripts running and the UIs that you see are all the ones in PlayerGui
.
Say this was your code:
game.StarterGui.ScreenGui.Frame.TextLabel.Text = "Yes hi"
This change will be seen once you respawn.
game.Players.LocalPlayer.PlayerGui.ScreenGui.Frame.TextLabel.Text = "Yes hi"
This change will be seen immediately.
Properties and Variables
Can’t think of a good title, but people often assume local value = numberValue.Value
(for example) will store a reference to the actual Value
property in the variable. So that they can go value = value + 5
or something to change the property.
Well all that does is store the current value at the time the script ran. It won’t update on its own: you need to do this yourself. Changing the variable value only changes the variable value, not the property itself.
It’s important to know the difference between reference and value.
Reference
Lua passes objects (tables, threads, userdatas, functions) by reference. Part of this means that variables and table fields contain references to these objects and not the objects themselves.
Think of references as arrows. Arrows point to something. Like it might point to a gas station right across the street. The arrow isn’t the gas station itself it just points to it.
local t = {'a', 'b', 'c'};
local t2 = {'a', 'b', 'c'};
local t_ref = t;
print("t == t2:", t == t2, "t == t_ref:", t == t_ref);
Output
t == t2: false t == t_ref: true
t
and t_ref
point to the same exact table. t2
is different even if it has the same elements in the same position.
Let’s now remove a few things.
table.remove(t_ref, 2);
print(t_ref[2], t[2], t2[2]);
Output
c c b
Value
Lua passes numbers, booleans etc by value.
local n = 8;
local n_ref = n; -- not even a reference lol
n = n + 5;
print(n, n_ref);
Output
13 8
Both variables have different memory so changing 1 won’t change the other.
The fix is to have your variables point to the number value object (for example) itself and make direct accesses to the Value
property to read it or write to it.
Using GetChildren table to modify children
Can’t think of a title for this one either. But lots of people looking for a quick way to change a property in all children, have code looking something like so:
game.Workspace.Model:GetChildren().BrickColor = BrickColor.Random();
:GetChildren
returns a table of all the children of an object, and all you’re doing in that example is adding a BrickColor
field to the table.
You need to traverse this table, so you can get each child.
for _, v in ipairs(game.Workspace.Model:GetChildren()) do
v.BrickColor = BrickColor.Random();
end
Conclusion
I go over a few common mistakes, and a solution to them. I hope you found this helpful and if you see anyone commit any of these mistakes do share this to them. I know there’s more mistakes, and do please tell me of them so I can add them to the list.