How to continue a loop after a wait

if i had a script that went

while wait() do
     print("hi")
     wait(5)
     print"hi2")
end

how oculd i make it so it still prints hi2 after 5 seconds but instead of waiting 5 seconds to print hi again it continues the loop but still prints hi2

4 Likes

If I’m understanding correctly, initially you want to print “hi” wait 5 seconds then print “hi2”, but rather than printing “hi” on the next iteration, you want to only print “hi2”? If so, this would work:

print("hi")

while wait() do
    wait(5)
    print("hi2")
end

So now, “hi” will print only once, as it’s outside the loop, and constantly print “hi2” from now on.

1 Like

i want it to print hi2 after five seconds but not have to wait 5 seconds for it to print hi again i want it to always print hi but print hi2 after every five seconds

like it continues the loop but still prints after five seconds

Ah I see, then you could use two loops? One that constantly prints “hi” and one that prints “hi2” every 5 seconds. With the current way you’re soing it, the script would get stuck so two loops wouldn’t work… That’s where threads come in.

We can simply spawn two tasks, each with the individual loops like so (it’s important to note that these two things will be in their own thread, a pipeline of sorts, that don’t have to wait for the other to finish execution’, really useful things if you know how to use them properly):

-- Our "hi" loop.
task.spawn(function()
    while task.wait() do
        print("hi")
    end
end)

-- Our "hi2" loop.
task.spawn(function()
    while task.wait(5) do
        print("hi2")
    end
end)
1 Like

Here’s a good post on threads here: Help With Understanding Threads and Multithreading

heres my script:

i want the part where it said wait(5) to not stop the loop

so i want it where it says wait(5) that what i put after that line still happens after 5 seconds but the loop will restart but the lines after wait(5) still happen

Alright, so putting task.spawn(function() on line 9 (relative to that script) and everything downward until the wait(5) (including the wait 5) and put end) below the wait(5). That will resolve the loop not stopping with wait(5), but right now it’s just going to spawn a lot of tasks and we don’t want that, so we need to have some form of boolean above line 1, to toggle when our task is done, mind sending the script please? :slight_smile:

like this?

wait(6)
while wait() do
	for i, v in pairs(game.Workspace.Area1DummySpawn:GetChildren()) do
		if v:IsA("BasePart") then
			if v:FindFirstChild("Area1Dummy") then
				for _, dummypart in pairs(v:FindFirstChild("Area1Dummy"):GetChildren()) do
					if dummypart:IsA("BasePart") then
						if v:WaitForChild("Area1Dummy").Health.Value == 0 then
							task.spawn(function()
								for _, playertags in pairs(v:GetChildren()) do
									if playertags:IsA("StringValue") then
										if game.Players:FindFirstChild(playertags.Name) then
											print(playertags)
											game.ReplicatedStorage.GiveMoney:FireServer(v, playertags.Name)
											game.ReplicatedStorage.GiveMoney.OnClientEvent:Connect(function()
												playertags:Destroy()
											end)
										end
									end
								end
								v.Area1Dummy.Parent = game.ReplicatedStorage
								for _, trash in pairs(game.ReplicatedStorage:GetChildren()) do
									if trash:FindFirstChild("Health") then
										if trash:FindFirstChild("Left Arm") then
											trash:Destroy()
										end
									end
								end
								wait(5)
							end)
							v.Used.Value = false

							local dummy = game.Workspace.Area1Dummy:Clone()

							if v.Used.Value ~= true then
								dummy:SetPrimaryPartCFrame(v.CFrame)

								v.Used.Value = true
								dummy.Parent = v
							end
							v.Used.Value = true

						end
					end

				end
			end
		end
	end
end
1 Like

Alright, changed the code up, I’ve explained with comments the reasoning for doing this as well.

local runOurTaskBool = true

wait(6)
while wait() do
	for i, v in pairs(game.Workspace.Area1DummySpawn:GetChildren()) do
		if v:IsA("BasePart") then
			if v:FindFirstChild("Area1Dummy") then
				for _, dummypart in pairs(v:FindFirstChild("Area1Dummy"):GetChildren()) do
					if dummypart:IsA("BasePart") then
						if v:WaitForChild("Area1Dummy").Health.Value == 0 then
							task.spawn(function()
                                
                                --[[ What we're doing here is, as we don't want this task to run 
                                    every single time, we're adding a condition to return straight away from it,
                                    which will dispose of the newly spawned task right away. ]]
                                if not runOurTaskBool then return end

                                -- Then we set our value to false, so no other tasks can spawn until the below code is done.
                                runOurTaskBool = false

								for _, playertags in pairs(v:GetChildren()) do
									if playertags:IsA("StringValue") then
										if game.Players:FindFirstChild(playertags.Name) then
											print(playertags)
											game.ReplicatedStorage.GiveMoney:FireServer(v, playertags.Name)
											game.ReplicatedStorage.GiveMoney.OnClientEvent:Connect(function()
												playertags:Destroy()
											end)
										end
									end
								end
								v.Area1Dummy.Parent = game.ReplicatedStorage
								for _, trash in pairs(game.ReplicatedStorage:GetChildren()) do
									if trash:FindFirstChild("Health") then
										if trash:FindFirstChild("Left Arm") then
											trash:Destroy()
										end
									end
								end
								wait(5)

                                -- After our 5 seconds are up, we're happy to spawn a new task in the future again. :)
                                runOurTaskBool = true
                                return
							end)
							v.Used.Value = false

							local dummy = game.Workspace.Area1Dummy:Clone()

							if v.Used.Value ~= true then
								dummy:SetPrimaryPartCFrame(v.CFrame)

								v.Used.Value = true
								dummy.Parent = v
							end
							v.Used.Value = true
						end
					end
				end
			end
		end
	end
end

This should do the trick, forgot to toggle the task spawning off, along with returning (to escape the task, I’m sure it implicitly returns anyway, but just to make sure).

all that script does is not wait adn just run the stuff after wait(5) infinitly

The code here would run infinitely, yes:

v.Used.Value = false

local dummy = game.Workspace.Area1Dummy:Clone()

if v.Used.Value ~= true then
    dummy:SetPrimaryPartCFrame(v.CFrame)

    v.Used.Value = true
    dummy.Parent = v
end
v.Used.Value = true

But the code inside of the task.spawn() is its own independant code flow, which won’t ever run, until that ‘runOurTaskBool’ is true. So for a 5 second period of time, it’ll only be running the above code. Is that not what you were after?

i want to switch it around so that the top code runs infinitely and the bottom after wait(5) only runs after the top runs if the health == 0 is true

1 Like

Ah gotcha, we just need to literally switch it, will do so now for you. :slight_smile:

local runOurTaskBool = true

wait(6)
while wait() do
	for i, v in pairs(game.Workspace.Area1DummySpawn:GetChildren()) do
		if v:IsA("BasePart") then
			if v:FindFirstChild("Area1Dummy") then
				for _, dummypart in pairs(v:FindFirstChild("Area1Dummy"):GetChildren()) do
					if dummypart:IsA("BasePart") then
						if v:WaitForChild("Area1Dummy").Health.Value == 0 then
                            for _, playertags in pairs(v:GetChildren()) do
                                if playertags:IsA("StringValue") then
                                    if game.Players:FindFirstChild(playertags.Name) then
                                        print(playertags)
                                        game.ReplicatedStorage.GiveMoney:FireServer(v, playertags.Name)
                                        game.ReplicatedStorage.GiveMoney.OnClientEvent:Connect(function()
                                            playertags:Destroy()
                                        end)
                                    end
                                end
                            end
                            v.Area1Dummy.Parent = game.ReplicatedStorage
                            for _, trash in pairs(game.ReplicatedStorage:GetChildren()) do
                                if trash:FindFirstChild("Health") then
                                    if trash:FindFirstChild("Left Arm") then
                                        trash:Destroy()
                                    end
                                end
                            end

                            task.spawn(function()
                                
                                --[[ What we're doing here is, as we don't want this task to run 
                                    every single time, we're adding a condition to return straight away from it,
                                    which will dispose of the newly spawned task right away. ]]
                                if not runOurTaskBool then return end

                                -- Then we set our value to false, so no other tasks can spawn until the below code is done.
                                runOurTaskBool = false

                                -- We'll wait for 5 seconds initially from this point.
                                wait(5)
							    v.Used.Value = false

							    local dummy = game.Workspace.Area1Dummy:Clone()

							    if v.Used.Value ~= true then
								    dummy:SetPrimaryPartCFrame(v.CFrame)

								    v.Used.Value = true
								    dummy.Parent = v
							    end
							    v.Used.Value = true

                                -- After our code is done, we're happy to spawn a new task in the future again. :)
                                runOurTaskBool = true
                                return
                            end)
						end
					end
				end
			end
		end
	end
end

it still stop the loop and waits 5 seconds

i just want the lines after wait(5) to still happen after 5 seconds but the loop to restart right away and not wait 5 seconds

This should most definitely not stop the loop entirely, after the task.spawn() code runs, it should instantly go back to the while wait() do at the top and work it’s way down from there, and because we have a task.spawn() still running (thanks to our runOurTaskBool keeping track of this), it will run the top bit still, but not our task.spawn() bit, UNTIL runOurTaskBool is true again.

In that case, there must be something else making it re-loop. Try and add a breakpoint and step through the code to check what’s happening. :slight_smile:

A post from the docs explaining breakpoint debugging, saved me a lot of trouble with things in the past and I hope it does the same for you as well: Debugging | Documentation - Roblox Creator Hub

shouldt there just be a way to restart the loop and still continue it at the same time

Alright, done some changes on my end, found a few issues of which I’ve commented/tagged as such. I’m convinced it shouldn’t halt the loop, I’m removing my boolean I put above to stop the task from running, so this implementation WILL constantly create tasks but just want to see where it goes. :slight_smile:

local WS = game:GetService("Workspace")
local RS = game:GetService("ReplicatedStorage")

wait(6)

while wait() do
    local areaOneDummySpawn = WS:FindFirstChild("Area1DummySpawn")
    if not areaOneDummySpawn then continue end

    for i, v in ipairs(areaOneDummySpawn:GetChildren()) do
        if not v:IsA("BasePart") then continue end

        local areaOneDummy = v:FindFirstChild("Area1Dummy")
        if not areaOneDummy then continue end

        for _, dummypart in ipairs(areaOneDummy:GetChildren()) do
            if not dummypart:IsA("BasePart") then continue end
            if areaOneDummy.Health.Value > 0 then continue end

            for _, playertags in ipairs(v:GetChildren()) do
                if playertags:IsA("StringValue") then
                    if game.Players:FindFirstChild(playertags.Name) then
                        print(playertags)

                        local giveMoneyEvent = RS:FindFirstChild("GiveMoney")
                        if not giveMoneyEvent then continue end

                        giveMoneyEvent:FireServer(v, playertags.Name)

                        --[[ Initially, you would have been constantly connecting a function to a client event,
                            creating multiple connections you didn't need. This still will and might be worth a tidy-up,
                            but now at least we dispose of the connection. ]]
                        local giveMoneyClientEventConnection
                        giveMoneyClientEventConnection = giveMoneyEvent.OnClientEvent:Connect(function()
                            playertags:Destroy()
                            giveMoneyClientEventConnection:Disconnect()
                            giveMoneyClientEventConnection = nil
                        end)
                    end
                end
            end

            areaOneDummy.Parent = RS

            for _, trash in ipairs(RS:GetChildren()) do
                if trash:FindFirstChild("Health") then
                    if trash:FindFirstChild("Left Arm") then
                        trash:Destroy()
                    end
                end
            end

            --[[ This should definitely not halt the loop... It should instantly go back to 'while wait() do' 
                after this, it won't have even finished the wait(5) before it gets back to the while wait() do. ]]
            task.spawn(function()
                wait(5)

                v.Used.Value = false

                local dummy = areaOneDummy:Clone()

                if v.Used.Value ~= true then
                    dummy:SetPrimaryPartCFrame(v.CFrame)

                    v.Used.Value = true
                    dummy.Parent = v
                end
                v.Used.Value = true

                return
            end)
        end
    end
end