How to loop code without crashing studio?

Hello, I’m wanting to have this code run each time that a player clicks on the cardslot, and not just one time, but whenever I apply the loop to my code, it ends up running out my timer quickly, and when I try to stop the test session, my studio ends up crashing.
I am a fairly newer scripter, so some of the methods I applied here might not be the best.

For the timer portion of the script, I use a while true do loop that gradually subtracts 1 from a Number value I have in a Values folder as long as there hasn’t been more than 50 balls dropped and the time value is above 0.
The script works just fine otherwise.

I did try searching on the dev forum, but I didn’t see anything that said ways to prevent a loop from crashing outside of applying a wait, although I found that the game runs normally if I put the wait value at 15, although the studio still crashes when I try and stop the test session, and the script doesn’t allow for the machine to be played afterward.

Here is my code below. I would appreciate any help.

---Variables
local CardReader = script.Parent.CardReader
local CardReaderText = CardReader.Cardslot.SurfaceGui.TextLabel
local DeadZone = script.Parent.DeadZone
local Button = script.Parent.Button
local GameboardText = script.Parent.GameBoard.Gameboard.SurfaceGui.TextLabel
local JackpotDisplay = script.Parent.Jackpot.JackpotDisplay.SurfaceGui.TextLabel
local Balls = game.ServerStorage.Balls
local VALUES = script.Parent.Values
local ControlGame = script.Parent.Button.button.ControlGame
local DropZones = script.Parent.RotatingPlatforms.DropZones
local function VictorySequence()
	VALUES.LastGameWon.Value = true
	GameboardText.Text = "You've hit the jackpot of " .. #VALUES.Jackpot.Value.. " tickets! Congratulations!"
	wait(15)
	repeat
		VALUES.VictorySequenceTime.Value = VALUES.VictorySequenceTime.Value - 1
		wait(1)
	until VALUES.VictorySequenceTime.Value == 0
	repeat
		local ballcopy = Balls:Clone()
		ballcopy.Parent = game.Workspace
		ballcopy.Anchored = false
		wait(.2)
	until VALUES.VictorySequenceTime.Value == 0
	if VALUES.VictorySequenceTime.Value == 0 then
		VALUES.JackpotValue.Value = VALUES.DefaultJackpotValue.Value
		JackpotDisplay = VALUES.DefaultJackpotValue.Value
		VALUES.GameFinished.Value = false
		VALUES.VictorySequenceTime.Value = 30
	end
end
JackpotDisplay.Text = VALUES.JackpotValue.Value
---Game Code
function StartGame()
while true do
wait(10)
		CardReader.Cardslot.ClickDetector.mouseClick:Connect(function(hit)
			if VALUES.IsPlaying.Value == false then  --- Checks that nobody is playing the machine
				CardReaderText.Text = "Enjoy your game!"
				wait(2)
				CardReaderText.Text = "Game in progress."
				VALUES.IsPlaying.Value = true
			end
		end)
		VALUES.IsPlaying.Changed:Connect(function()
			if VALUES.IsPlaying.Value == true then
				VALUES.AmountDropped.Value = 0		---Resetting previous game's values
				VALUES.TouchedJar.Value = 0
			end
			VALUES.LastGameWon.Changed:Connect(function()
				if VALUES.LastGameWon.Value == true then
					VALUES.JackpotValue.Value = VALUES.DefaultJackpotValue.Value
					JackpotDisplay = VALUES.JackpotValue.Value
				end
			end)
			GameboardText.Text = "Welcome to Quik Drop!"
			wait(4)
			GameboardText.Text = "The goal is to drop all 50 balls into the bucket before the time runs out."
			wait(4)
			GameboardText.Text= "If you drop all 50 balls into the bucket, you will win the Jackpot!"
			wait(4)
			GameboardText.Text = "Good luck!"
			wait(4)
			ControlGame.Disabled = false
			while VALUES.Timer.Value > 0 and VALUES.AmountDropped.Value < VALUES.MaximumBallCount.Value do
				VALUES.Timer.Value = VALUES.Timer.Value - 1
				GameboardText.Text = VALUES.Timer.Value
				wait(1)
			end	
			if VALUES.AmountDropped.Value >= VALUES.MaximumBallCount.Value or VALUES.Timer.Value == 0 then
				ControlGame.Disabled = true
				Balls.Parent = game.ServerStorage
				VALUES.GameFinished.Value = true
				if VALUES.GameFinished.Value == true then
					GameboardText.Text = "The game has finished! Let's see how you did!"
					wait(4)
					if VALUES.TouchedJar.Value < VALUES.BallsNeeded.Value then
						GameboardText.Text = "It looks like you did not quite get all 50 balls."
						wait(4)
						GameboardText.Text = "You got "..VALUES.TouchedJar.Value.. " balls in the bucket."
						wait(4)
						GameboardText.Text = "Try again next time!"
						wait(4)
						VALUES.JackpotValue.Value= VALUES.JackpotValue.Value + 5
						JackpotDisplay.Text = VALUES.JackpotValue.Value
						GameboardText.Text = "Quik Drop"
						print (JackpotDisplay)
					elseif VALUES.TouchedJar.Value == VALUES.BallsNeeded.Value then
						VictorySequence()					
							end
						end
					end
				end)		
			end	
		end
StartGame()
1 Like

It might be because you’re adding more connections to your events every time you go through a loop, taking up a lot of memory, and also lagging out the game whenever those evens fire. You only need to connect the functions once, not continuously.

I have a feeling that might be caused by the touched events I have in some of my other scripts, which are meant to destroy the balls whenever it comes into contact with a dropzone or a deadzone. I’ll show them under this comment, the only difference between them is that one of them adds to a value if it hit a dropzone. I’ll also go ahead and see if I can get a screenshot of the memory in the dev console.

Balls = game.ServerStorage.Balls
script.Parent.Touched:Connect(function(hit)
	if Balls then
		wait(.2)
		hit:Destroy()
	end
end)
local Balls = game.ServerStorage.Balls
local VALUES = script.Parent.Parent.Parent.Parent.Values
local debounce = false
script.parent.Touched:Connect(function(hit)
	if not debounce then
		debounce = true
		wait(.2)
		hit:Destroy()
		VALUES.TouchedJar.Value = VALUES.TouchedJar.Value + 1
		debounce = false
	end
end)

I don’t see anything wrong with your ball script, although it doesn’t to hurt add a denounce to the first one as well.


Here is what shows up in the memory on the console. it seems to spike up a little bit when I start dropping balls, then it goes down when the game detects that the game is finished and flatlines around 45.275 mb.

How long does the game last? Does it last more than 10 second?

The game lasts for 30 seconds and stops when either all 50 balls are dropped or the timer runs out. Here is part of the script I posted before with that section of the code here:

while VALUES.Timer.Value > 0 and VALUES.AmountDropped.Value < VALUES.MaximumBallCount.Value do
				VALUES.Timer.Value = VALUES.Timer.Value - 1
				GameboardText.Text = VALUES.Timer.Value
				wait(1)
			end	
			if VALUES.AmountDropped.Value >= VALUES.MaximumBallCount.Value or VALUES.Timer.Value == 0 then
				ControlGame.Disabled = true
				Balls.Parent = game.ServerStorage
				VALUES.GameFinished.Value = true

Nothing seems wrong with this code either, except that the if statement is redundant, as the while loop only breaks when the if statement is true.

Back to the first code, in StartGame, why exactly do you need the first while true do? It doesn’t seem to be doing anything except reconnecting events that were already connected.

I had put the while true do loop there in an attempt to see if that would allow for the player to play the machine more than once, since atm it only works once and doesn’t trigger again even after clicking the cardslot. Like I said in my OP, I am fairly newer to scripting, so there could be something I’m missing here that I don’t realize yet.

when you connect a function to an event,
(e.g.
CardReader.Cardslot.ClickDetector.mouseClick:Connect(function(hit)

end)

)

The connection doesn’t go away when the event is triggered. Instead, every time the event is triggered, it’ll run the same code. by constantly connecting the events every 10 seconds, you’re telling the game to run the code multiple times when the event is triggered, which can really ruin a lot of stuff, let alone the fact that more connections means more memory usage, and continuously adding connections without removing old ones can cause memory leak.

The connection doesn’t go away when the event is triggered. Instead, every time the event is triggered, it’ll run the same code. by constantly connecting the events every 10 seconds, you’re telling the game to run the code multiple times when the event is triggered

Is this true when you have 2 scripts that take the same input to activate an event? I just tried applying a debounce to both the cardslot code and the game control code, and it did reduce the memory usage to the range of 41-43 mb on a few test sessions, and it didn’t crash, but still didn’t loop.

The game doesn’t loop because nowhere in your code do you set IsPlaying.Value back to false, so when the player clicks on the cardslot again, it sees that IsPlaying.Value == true and does nothing,

I want to point something out that’ll give you problems in a minute, your connection to IsPlaying.Changed that actually starts the game takes into account when the game was being started or stopped only for resetting values, and not for actually starting the game. This means that when you do set IsPlaying.Value back to false, it’ll start the game as if you set it to true. I recommend putting this at the start of the function you’re connecting to stop it from running when the game is stopped:

if VALUES.IsPlaying.Value == false then
    return
end

Yeah, I was about to apply that before I saw your response, thanks for the help, although I feel dumb for missing something that was so simple as forgetting to set a value back to false. I still have a learning curve to follow

Don’t worry about forgetting stuff, I forgot that return is for functions and break is for loops when writing that response. Anyways, you might also want to connect LastGameWon.Changed outside of IsPlaying.Changed, as it’ll reconnect every time the game starts and lead to memory leak.

The machine doesn’t respond when I do that, which softlocks the script from working properly

Anyways, you might also want to connect LastGameWon.Changed outside of IsPlaying.Changed, as it’ll reconnect every time the game starts and lead to memory leak.

Also will do.

I don’t know why that didn’t work, but I guess you can also try putting the part of the function that starts the game inside the if statement that checks if the value is true, you would only start the game if the game is being set to being played. You can also add print statements nearby to probe the code to see which parts run and which parts don’t.

Ok, so I tried adding a check that requires a bool value to be true along with the IsPlaying bool value and now it doesn’t trigger the intro sequence, and no errors in output. The value I added is changed though.

CardReader.Cardslot.ClickDetector.mouseClick:Connect(function(hit)
			if VALUES.IsPlaying.Value == false then  --- Checks that nobody is playing the machine
				CardReaderText.Text = "Enjoy your game!"
				wait(2)
				CardReaderText.Text = "Game in progress."
				VALUES.IsPlaying.Value = true
				VALUES.PassedCardReader.Value = true
			end
		end)
			VALUES.LastGameWon.Changed:Connect(function()
			if VALUES.LastGameWon.Value == true then
			VALUES.JackpotValue.Value = VALUES.DefaultJackpotValue.Value
			JackpotDisplay = VALUES.JackpotValue.Value
						end
					end)			
				end
			if VALUES.IsPlaying.Value and VALUES.PassedCardReader.Value == true then
			VALUES.AmountDropped.Value = 0		---Resetting previous game's values
			VALUES.TouchedJar.Value = 0

You’re changing the IsPlaying value before changing the PassedCardReader value, so the event is triggered before PassedCardReader is true.

I’m playing a game with my friends, so I might not be able to respond for a while.