I want my script to stop looping and sending 800 requests to this module script
mainscript:
wait(2)
local Players = game.Players
local ReplicatedStorage = game.ReplicatedStorage
local ServerStorage = game.ServerStorage
local ChangeText = game.ReplicatedStorage.ChangeText
local InGame = game.ServerStorage.Values.InGame
local PlayersLeft = game.ServerStorage.Values.PlayersLeft
local Functions = require(script.Functions)
while true do
ChangeText:FireAllClients("Waiting for 2 players")
repeat wait() until #game.Players:GetPlayers() >= 2
local Functions = require(script.Functions)
ChangeText:FireAllClients("Starting")
wait(7)
Functions.SetPlayersLeftValue()
for _, player in pairs(Players:GetPlayers()) do
Functions.SpawnPlayerValue(player, false)
end
Functions.resetKills()
wait(3)
ChangeText:FireAllClients("Loading Map")
wait(3)
Functions.TeleportPlayer()
ChangeText:FireAllClients("")
wait(5)
Functions.GetPlayerKnifesAndGiveItToThem()
repeat wait() until game.ServerStorage.Values.PlayersLeft.Value <= 1
game.ServerStorage.Values.PlayersLeft.Value = 0
ChangeText:FireAllClients("Game Over!")
wait(7)
Functions.KillPlayers()
end
Module script:
local Functions = {}
function Functions.resetKills()
for _, player in pairs(game.Players:GetPlayers()) do
player.KillsThatRound.Value = 0
end
end
function Functions.checkSpawned(player)
if player.SpawnedInMap.Value == true then
return true
elseif player.SpawnedInMap.Value == false then
return false
end
end
function Functions.SpawnPlayerValue(player, value)
player.SpawnedInMap.Value = value
end
function Functions.TeleportPlayer()
for _, player in pairs(game.Players:GetPlayers()) do
local SpotsToSpawnIn = {}
local TheirSpot
for i, v in pairs(workspace.SpawnPoints["2"]:GetChildren()) do
table.insert(SpotsToSpawnIn, v)
end
for i, v in pairs(SpotsToSpawnIn) do
print(v)
local number = SpotsToSpawnIn[math.random(1, #SpotsToSpawnIn)]
TheirSpot = number
print(number)
end
if player.Character == nil then
repeat wait() until player.Character ~= nil
player.Character.HumanoidRootPart.CFrame = TheirSpot.CFrame
else
player.Character.HumanoidRootPart.CFrame = TheirSpot.CFrame
end
end
end
function Functions.GetPlayerKnifesAndGiveItToThem()
for _, player in pairs(game.Players:GetPlayers()) do
local CurrentKnifeValue = player.CurrentKnifeValue.Value
local TheirKnife = game.ServerStorage.Knifes:FindFirstChild(CurrentKnifeValue)
if TheirKnife ~= nil then
local Cloned = TheirKnife:Clone()
Cloned.Parent = player.Backpack
end
end
end
function Functions.SetPlayersLeftValue()
print("s")
for _, v in pairs(game.Players:GetPlayers()) do
game.ServerStorage.Values.PlayersLeft.Value = game.ServerStorage.Values.PlayersLeft.Value + 1
v.inGame.Value = true
end
end
function Functions.KillPlayers()
for _, v in pairs(game.Players:GetPlayers()) do
if v.Character == nil then
repeat wait() until v.Character ~= nil
v.Character.HumanoidRootPart.CFrame = CFrame.new(879.31, -14.554, 2603.859)
else
v.Character.HumanoidRootPart.CFrame = CFrame.new(879.31, -14.554, 2603.859)
end
end
end
return Functions
i am aware of the while true loop but that loop is slowed down by waits and the repeat wait.
If it is firing that many times, something is really going wrong. Check every repeat, for loop, and while true loop. Make sure that loop isn’t running too many times - add a lot of prints. Once you find out where exactly your problem lies, you can really dive deeper. If you have any questions, feel free to ask!
Is the module script really necessary then? It certainly makes the script appear cleaner, but it isn’t that long. . . If I were you, I would revert it to before you added the module script. You can have
local function NameHere()
end
before the while true loop, and just call them. That may be your answer.
local matchStarted = false
function lobbyChecker(_) -- I use '_' because you don't need to consider player added or removed unless you want to
if not matchStarted and #game.Players:GetPlayers() >= 2 then
matchStarted = true
-- do the match stuff here
matchStarted = false
end
end
game.Players.PlayerAdded:Connect(lobbyChecker)
game.Players.PlayerRemoving:Connect(lobbyChecker)
Be aware that over time, your script will just stop because of Roblox’s default Script Timeout Length. You can’t infinitely keep a loop running unless you change it manually in Studio, but I don’t recommend it.
Theoretically yes. Technically it’s bad practice, and Roblox Studio opts to place a Script Timeout Length for you by default, but you can easily change it. The reason they place the timer is to avoid you using it in the first place as loops should be finite.
Here’s a good source on managing if you absolutely HAVE to use an infinite loop.
EDIT: More info…
Furthermore, a script with connections would run ONCE and then saved as instances until needed. Even if it is connected forever, the script itself is not running forever. Which is why connections are the way to go since the engine is made for you. An infinite loop is only ever necessary by the engine, not the stuff built on top of it which is what you’re primarily doing when scripting in Roblox. If you need an “Infinite loop” for example you can do so with things such as: In local scripts runService.RenderStepped, runService.Heartbeat:Wait() and such things which are built on top of the running engine.
I’m still a bit confused. Do infinite wait() loops last forever in actual servers / games? Sometimes people afk in games overnight and I don’t understand how those games don’t timeout.
Also:
What would be a good practice if you need an infinite game loop? Something like this:
while true do
StartGame()
wait(3)
GiveItems()
wait(60)
EndGame()
wait(10)
end
So it can run forever, depending, if you add a yields to it where it briefly pauses and such. Now if you want to get really technical, wait() itself is not even a “good” yielding technique. It’s a lot to explain but you can google “Is wait() good yielding roblox” and you’ll get a bunch of results on it.
Good practice is relative though. Like I said depending on what you’re trying to do, there are so many ways to implement it. But connections is definitely the best.
For your last code piece, a good replacement, even though longer would be:
-- we only want to run when players join, so why use infinite loop
game.PlayersAdded:Connect()
-- now we also want to take into account when they leave
game.PlayersRemoving:Connect()
-- now what do they respond to?
function matchLoopHandler()
-- now this runs when players leave and join... check player count
-- also add a debounce so that we don't repeatedly run everytime a player joins a leaves
if game.Players:GetPlayers() > minimumPlayercount and not debounce then
debounce = true
-- here we can now do the match loop stuff
matchLoop()
debounce = false -- this should only hit once theyre are not sufficient players... I'll show you further below why
end
end
--- Now the bread and butter of the loop
-- The handler was the "while" part
-- This is what's inside the "while"
function matchLoop()
GameStart()
-- whatever here
GameEnd()
-- Now, before we return to the main part, we can do the next loop using tail recursion
if game.Players:GetPlayers() > minimumPlayercount then
matchLoop() -- loop to the beginning
end
-- return all the way and end the "while" loop
end
Clean code without comments:
local debounce = false
function matchLoop()
RunGame()
if #game.Players:GetPlayers() > 5 then
matchLoop()
end
end
function matchLoopHandler()
if #game.Players:GetPlayers() > 5 and not debounce then
debounce = true
matchLoop()
debounce = false
end
end
game.Players.PlayerAdded:Connect (matchLoopHandler)
game.Players.PlayerRemoving:Connect(matchLoopHandler)
Last post about this LOL:
A bonus about using this is if ANYTHING errors, a while loops would break and teh script will stop, making the game unplayable. If a matchLoop errors, it will break that thread, however will reset itself upon the next call of PlayerAdded or PlayerRemoving.