My code looks like this, and I am assuming it is wrong as ROBLOX tells me v is a nil value.
while true do wait() repeat for i, v in pairs(game.Players:GetPlayers()) do if v.TeamColor == BrickColor.new("Bright red") then if v.Character.Humanoid.Health == "100" then wait() end end end until v.Character.Humanoid.Health == "0"
If you can't tell, I want the script to look for the players on Bright red team and then to check if health is 100, if it is, it is just going to wait() / repeat those lines. I want it to stop repeating when the player (or v.Character) has a health of 0. Could I add another for i, v in pairs after the until? ROBLOX still shows red lines on it so I am assuming I can't. How else can I get around this?
Roblox errors "attempt to index a nil value" because your v
variable is out of scope. "attempt to index a nil value" means you are trying to access a variable's member through the '.
' or ':
' operators but that variable is nil; it has no value.
About a variable's scope:
When we say a variable is out of scope, we mean the variable's lifetime is over; It does not exist anymore. In this particular example, this is due to the fact that the variables i
and v
are local to your for
loop. In other words, the variables are deleted after the for
loop is done executing; at the end
of the loop.
There are two kinds of variables in Lua (not to be confused with a variable's type): Global variables and local variables.
A global variable's scope is that of the whole script. It exists throughout the entire "file".
A local variable's scope is the level of the block in which it is declared in (starting at the line following the one it was declared on). They are introduced by prefixing them with the local
keyword.
E.g:
-- 'a' is global variable. It exists and can be used through the whole script. a = 2 if a == 2 then local b = "test" -- 'b' is a local variable. Its scope (and so its lifetime) is limited -- to the block following this 'if' statement and all the blocks -- "under", or "inside", it. Functions; 'while', 'for' and 'repeat ... -- until' loops; as well as 'do ... end' statements are also blocks. -- A block, and by extension its scope level, ends whenever an -- 'else', 'elseif' or 'end' keyword is encountered by Lua. if b == "test" then -- 'b' still exists here. local c -- You don't need to assign them a value by the way. -- A local variable declared with no value will by default -- have the value 'nil'. -- -- For global variables, this is redundant and thus will -- throw an error saying "'=' expected near '<eof>'". end end -- 'b' ceases to exist here; It is now out of scope. -- Any reference to 'b' will return nil, and so any -- attempt to access a member of that nil value -- will error out "attempt to access a nil value" -- 'd' is a variable local to the global scope. There is -- a minor subtlety with a global variable. 'd's scope -- starts here and persists until the end of the file... local d = 4 function setValueOfE(value) e = value end -- ...whereas 'e's scope still starts at the top of the file. -- The difference is that 'e' can be used anywhere, -- EVEN ABOVE these lines and will still refer to the same -- global variable 'e' (although it's value will be nil until -- it is first assigned a value). setValueOfE(2) print(e) -- prints "2" e = 1 print(e) -- prints "1" do -- Just like local variables, local functions can only -- be called in the block they have been declared -- in (starting at the line following the declaration). -- Just like local variables, they can also be local to -- the global scope (Although I won't demonstrate -- this here, I figure you get the point). -- 'f' doesn't exist yet. f() -- "attempt to call global 'f', a nil value" -- 'f's scope starts here. local function f() print("Hello, World!") end f() -- prints "Hello, World!". -- A local function, like a global function can -- also call itself without problem. local function factorial(n) if n < 0 then error("n is negative", n) elseif n < 2 then return 1 else return n - factorial(n - 1) end end end -- 'f' and 'g' are now out of scope. f() -- "attempt to call global 'f' (a nil value)" g() -- "attempt to call global 'g' (a nil value)" -- a local or global function declaration is really -- just the same as variable assigned a "function value" -- (also known as anonymous function): local myFunction1 = function() print("Hello!") end local myFunction2 = function() print("World!") end -- Since in essence they are just variables, you could also -- pass them as a parameter to another function: local function execute(someFunction) -- receives 'someFunction' as a parameter -- and calls it. someFunction() end local function printHelloWorld() print("Hello, World!") end execute(printHelloWorld) execute(function() print("This works too!") end)
Alright, that's it for the theory. Let's jump to your problem.
There are two solutions to your problem:
Solution #1: Use a global variable
This is -- and any good Lua scripter will agree with me -- the easiest (as in, you won't have to change your script too much) but also ugliest way to solve this problem. While you won't have to rethink your script much, it is considered bad practice. Very bad. Unless you have a really good reason not to, you should always stick to local variables. True, global variables and functions are convenient. Simply by typing a = 5
or using the _G
table (_G.a = 5
, which is the exact same thing), you can create a variable that’s accessible from anywhere in your code. But there are also multiple reasons why this is bad. First of all, Lua is much more efficient and faster when working with local variables than global variables. Secondly, say I were to write something like this: string = "myString"
; In this case I would have completely trashed the string
library just because I wanted a variable named 'string
'! Whereas if I used a local variable, the string library (which is really just a global table filled with functions) would never have been modified. There are other cons to using global variables or the global table, but I won't discuss them all here. Let's just say they are out of scope of this answer. :)
Solution #2: Subscribing to the Died event
Instead of Wait()
ing for a player to die, you could instead subscribe to the Died
event of the player characters' Humanoid, here's an example:
function onDeath(character) print("Someone died") end function onPlayerAdded(player) -- For each player who joins the game, we... -- check their TeamColor. If they are in the bright red team then... if v.TeamColor == BrickColor.new("Bright red") then -- we obtain their character model through their Player instance... local character = v.Character -- we check if it exists, just to be sure. if character then -- If it exists then we look for an Humanoid object -- inside their character model... local humanoid = v:FindFirstChild("Humanoid") -- again, we check if it exists. if humanoid then -- If it exists then we "subscribe" (we also say "listen" -- or "connect") to it's Died event. By this, I really just -- mean passing it a function that will be called back -- when the event triggers. Such a function is known as -- a "Callback". That's a very original name, isn't? humanoid.Died:connect(onDeath) -- Our "onDeath" function will now always be called -- whenever someone on the bright red team dies. -- -- Note that players who already died once won't be -- affected. For this, you'd need to subscribe to the -- player's CharacterAdded event -- which is fired every- -- time a player's character respawns -- and connect -- your onDeath function callback each time the callback -- passed to CharacterAdded is called. I'll leave this to you -- as an excercise. end end end end -- We subscribe to the PlayerAdded event, which is fired whenever -- a player joins the game. game.Players.PlayerAdded:connect(onPlayerAdded)
Alright. That was a particularly long read but I hope it helped you and that maybe you've learned a few things. Please be sure to upvote and mark my answer as accepted if it did. If you still need help with this, feel free to leave me a message.