I am having issues, Whenever I try to run my Game script (indev), I try to access all the GUIs of the player's through pairs, yet it only accesses 1 player Gui. Can Someone help?
Here's the code Snippet:
--[[QuakeScape MainScript]]-- --=[[All people who See this script other than FOXmcloud021 or Steal this Script will be taxed...]]=-- --With their life...-- local LSounds = game.Lighting.LoseSounds:GetChildren() local WSounds = game.Lighting.WinSounds:GetChildren() local Maps = game.Lighting.Maps:GetChildren() while wait(5) do if game.Players.NumPlayers > 1 then for i,v in pairs(game.Players:GetChildren())do v.PlayerGui.TopBar.Frame.Visible = true v.PlayerGui.TopBar.Frame.TextLabel.Text = "Intermission..." wait(15) v.PlayerGui.TopBar.Frame.TextLabel.Text = "Choosing Map..." wait(10) end local MapChoose = math.random(1, #Maps) local MapChosen = Maps[MapChoose] for i,v in pairs (game.Players:GetChildren()) do v.PlayerGui.TopBar.Frame.TextLabel.Text = "Map Found!" wait(5) v.PlayerGui.TopBar.Frame.TextLabel.Text = "Loading map..." for i = 1,1,100 do v.PlayerGui.TopBar.Frame.TextLabel.Text ="Loading map... "..i.."%" wait(.15) end v.PlayerGui.TopBar.Frame.TextLabel.Text = "Map Loaded!" end MapChosenClone = MapChosen:Clone(game.Workspace) else for i,v in pairs(game.Players:GetChildren())do v.PlayerGui.TopBar.Frame.Visible = true v.PlayerGui.TopBar.Frame.TextLabel.Text = "There must be Another Player in order to Play this Game" end end end
I am highly assuming you are running this in a Server Side script, under Workspace or ServerScriptService. The reason it is not looping to all player's ScreenGuis is because of this wait() functions. Seriously, that's the problem. I know this because I have tried making a admin script and a laser tag game looping through all players using the same method presented. The way you can have the script loop through all players at once while not removing the waits if a technique called coroutines. Coroutines basically makes lines of code in a function to run almost like a separate script is being used (that's my best explanation of it). For your script you will want to use the following code:
coroutine.resume(coroutine.create(function() --coroutines are kind of functions themselves, so at the end of resume and create, add a "(" and then create a function, hence "function()". You can then add code to the next line. --Code Here end)) --You end the function, then you close the coroutine.create parenthesis and coroutine.resume parenthesis.
With coroutines, the wait time will do the wait for that player only. It is a useful technique especially if you know your script may break, due to a person leaving or something along those lines, the coroutine will break but the entire script will not. Though, caution when using coroutines because any errors will be hidden from the developer console.
As a final output your script should look like this when looping through players.
--[[QuakeScape MainScript]]-- --=[[All people who See this script other than FOXmcloud021 or Steal this Script will be taxed...]]=-- --With their life...-- local LSounds = game.Lighting.LoseSounds:GetChildren() local WSounds = game.Lighting.WinSounds:GetChildren() local Maps = game.Lighting.Maps:GetChildren() while wait(5) do if game.Players.NumPlayers > 1 then for i,v in pairs(game.Players:GetChildren()) do coroutine.resume(coroutine.create(function() --You can only resume a created coroutine, that's why it creates one in the parenthesis. v.PlayerGui.TopBar.Frame.Visible = true v.PlayerGui.TopBar.Frame.TextLabel.Text = "Intermission..." wait(15) v.PlayerGui.TopBar.Frame.TextLabel.Text = "Choosing Map..." end)) --End the function and coroutines. end wait(25) --I moved this wait and added time to it because the coroutine is basically a separate script and will not make the script wait to choose a map. Change if you need to. local MapChoose = math.random(1, #Maps) local MapChosen = Maps[MapChoose] for i,v in pairs (game.Players:GetChildren()) do coroutine.resume(coroutine.create(function() --And another coroutine was made! v.PlayerGui.TopBar.Frame.TextLabel.Text = "Map Found!" wait(5) v.PlayerGui.TopBar.Frame.TextLabel.Text = "Loading map..." for i = 1,1,100 do v.PlayerGui.TopBar.Frame.TextLabel.Text ="Loading map... "..i.."%" wait(.15) end v.PlayerGui.TopBar.Frame.TextLabel.Text = "Map Loaded!" end)) --End the function and coroutines. end MapChosenClone = MapChosen:Clone(game.Workspace) else for i,v in pairs(game.Players:GetChildren()) do --You will not need a coroutine here since it will be virtually simultaneous. But you actually may want to add a WaitForChild function for protection though. v:WaitForChild("PlayerGui").TopBar.Frame.Visible = true v:WaitForChild("PlayerGui").TopBar.Frame.TextLabel.Text = "There must be Another Player in order to Play this Game" end end end
Some people may complain that coroutine.wrap()
is more efficient, but I don't use it since I have not had much luck with it. Though I have seen coroutine.wrap()
go coroutine.wrap(function --Code end)()
in another script, which I haven't tried yet but will intend on doing.
Hopefully this answer helped and explained what coroutines are a bit, and hope that they help in the long run. If you need a further explanation to coroutines, checkout this wiki article.
Are you running this in a LocalScript? If so, then the reason why is that LocalScripts can only access the client's PlayerGui. Else if there is an error of joining players, try using Player:waitForChild'PlayerGui'
.