I have a basic minigame code.
Lobby > Intermission > Teleport Players > Winner > Lobby
The Intermission GUI countdown never shows when I play, so I'm stuck in the lobby. Everything works fine in studio. I've read similar issues to mine and tried using a LocalScript, but this prevents it from working in studio and game.
Heres the code:
function ChangeText(Text) local Players = game.Players:GetPlayers() for i = 1, #Players do Players[i].PlayerGui.Main.Time.Text = Text end end while true do for i = Intermission, 0, -1 do ChangeText('Intermission ' ..i) wait(1) end local Players = game.Players:GetPlayers() for i = 1, #Players do Players[i].Playing.Value = true end ChangeText('Game starting...') wait(2) GetMap() --//
Not sure where things are going wrong. Help is appreciated!
The problem is that you're trying to access the PlayerGui
of a player from the server. For security reasons Roblox has made it so you can't do this. However, this doesn't matter in studio because studio is the server and player, so it's not always an accurate testing device.
Instead of trying to change the text on line 4:
Players[i].PlayerGui.Main.Time.Text = Text
You're going to have to use a Remote Event. This allows communication between the player and the server. I'm not going to explain it here (if you want me to though I can explain it sometime later) but you should try to do some research and come back if you need any help.
Your error here is you're trying to make a local player change on the server. The reason this change is failing to work is because of how Server-Client relations work. You see, in the StarterGUI you most likely made your GUIs, they are replicated onto a player when they join, placed into a PlayerGui (which is in the LocalPlayer, and on the client)
When you referred for the server to change all the player's scripts, you told the script to change it in the PlayerGUI, which is on the client-side. Since your other script was on the server, it couldn't directly contact the player's GUI. If you'd like to learn more in general of FIlteringEnabled, and client-server relations, you can endeavor in here: https://medium.com/roblox-development/understanding-filteringenabled-part-1-3ccff00ba24c
Solution
To avoid this error from happening, what you need are RemoteEvents. These are to be created in the ReplicatedStorage. RemoteEvents are what you need for a server and its clients to communicate and exchange information. In your case, you're wanting the server to signal all the clients to change the text to a timer, or to announce when a game is starting. What they do is fire a command to the clients (which you specify). Then on the client's side, they can refer to that RemoteEvent, and use it to edit anything involving the client. (There's another way with using a client to fire the server, I'll get to that later)
When you place in the RemoteEvent, you can add a script to either, the Workspace, or ServerScriptService (You can do the ReplicatedStorage, too, but I would advise against that to avoid a mess with where your scripts are). On that script, you can simply fire the clients to change the time for intermission, as written below:
game:GetService("ReplicatedStorage").RemoteEvent:FireAllClients()
Sounds simple, right? If not, you 'll get the hang of it later. Now, as I had said previously, you need to do the changes on the client. So in terms of using RemoteEvents and GUIs, you can add a LocalScript to the GUI being changed, and allow for the timer to be done!
game.ReplicatedStorage.RemoteEvent.OnClientEvent:Connect(function() --Insert a time script here. (Preferably a for loop, unless you have a have made a number value for the time end)
Of course, once it's done, you want the server to be aware of when to announce the game is starting, and teleport players. That's where the other form of RemoteEvents come in. We can then visit back to that LocalScript we did from before, and add a little to it. (PS, you need to make another RemoteEvent)
game.ReplicatedStorage.RemoteEvent.OnClientEvent:Connect(function() --Insert a time script here. (Preferably a for loop, unless you have a have made a number value for the time --AFTER ENDING game.ReplicatedStorage.RemoteEvent2:FireServer() --Enter the game announcement text end)
It's pretty much the same context, but the roles are reversed in what to call for which script. Now, right when you fire the Server to teleport, it's going to get a RemoteEvent call from each client. Of course, this isn't ideal to have 10 commands fired at the server, because it can break the game! Now, on the regular script, we need to accompany it with this RemoteEvent, and a debounce, to allow only one command to be taken by the server.
debounce = true game.ReplicatedStorage.RemoteEvent:FireAllClients() game.ReplicatedStorage.RemoteEvent2.OnServerEvent:Connect(function() if debounce then not debounce --Insert teleport script with for i, v, in ipairs(game.Players:GetPlayers()) end end)
In the end, that's all what's to it, you just need some RemoteEvents for the server to tell the players and clients what to do, and for the clients to let the Server be aware of what to do at certain times. Hopefully this answers your question!