I’ve got a script that creates a coroutine, and can start/stop that coroutine. However, how can I restart the coroutine (even when if it finishes)?
local event = script.Parent:WaitForChild("Reloading")
local val = script.Parent.Parent:WaitForChild("Reloaded")
local state = script.Parent.Parent:WaitForChild("State")
local handle = script.Parent.Parent:WaitForChild("Handle")
local co = coroutine.create(function()
for i,v in pairs(handle:GetChildren()) do
if v:IsA("Sound") == true then
v.TimePosition = 0
end
end
-- play anims
wait(.5)
handle.Tear:Play()
handle.Tear.Ended:Wait()
wait(.5)
handle.SpitPaper:Play()
handle.SpitPaper.Ended:Wait()
wait(.7)
handle.Pour:Play()
handle.Pour.Ended:Wait()
wait(.5)
handle.Frizzen:Play()
handle.Frizzen.Ended:Wait()
wait(1)
handle.TakeOut:Play()
handle.TakeOut.Ended:Wait()
wait(.7)
handle.Ram:Play()
handle.Ram.Ended:Wait()
wait(.5)
handle.Ram:Play()
handle.Ram.Ended:Wait()
wait(1)
handle.TakeOut:Play()
handle.TakeOut.Ended:Wait()
val.Value = true
state.Value = "Idle"
end)
event.OnServerEvent:Connect(function(plr)
if state.Value == "Reloading" then
coroutine.close(co)
state.Value = "Idle"
else
if val.Value == false then
coroutine.resume(co)
state.Value = "Reloading"
end
end
end)
Why not create a new coroutine to restart it?
For a more organized approach I would consider looking at the Promise library when handling cancellable tasks but thats my preference.
how would i create a new coroutine that i can cancel outside of that function?
Why not just use the task
library? That basically creates a more efficient coroutine for you.
This makes it easier to restart it like dthecoolest suggested already. Rather than coroutine.resume()
which will not restart your coroutine, we can just use task.spawn()
to make a new one.
And you don’t need to use any external module for this.
local event = script.Parent:WaitForChild("Reloading")
local state = script.Parent.Parent:WaitForChild("State")
local handle = script.Parent.Parent:WaitForChild("Handle")
local ANIMATIONS : {{delay:number, track : AnimationTrack}} = {
{delay = 0.5, track = handle.Tear},
{delay = 0.5, track = handle.SpitPaper},
{delay = 0.7, track = handle.Pour},
{delay = 0.5, track = handle.Frizzen},
{delay = 1.0, track = handle.TakeOut},
{delay = 0.7, track = handle.Ram},
{delay = 0.7, track = handle.Ram},
{delay = 0.5, track = handle.Ram},
{delay = 1.0, track = handle.TakeOut},
}
local function hasAnimationFinished(thread : thread)
return not thread or coroutine.status(thread) == "dead"
end
local function playAnimations()
for _,child in handle:GetChildren() do
if child:IsA("Sound") then
child.TimePosition = 0
end
end
-- play animations in order
for _, animation in ipairs(ANIMATIONS) do
task.wait(animation.delay)
animation.track:Play()
animation.track.Ended:Wait()
end
state.Value = "Idle"
end
local reloading_thread : thread;
event.OnServerEvent:Connect(function(plr)
if state.Value == "Reloading" then
if not hasAnimationFinished(reloading_thread) then
task.cancel(reloading_thread)
end
state.Value = "Idle"
else
if hasAnimationFinished(reloading_thread) then
reloading_thread = task.spawn(playAnimations)
state.Value = "Reloading"
end
end
end)
PS: I also couldn’t help but improve your code a little bit, I hope that’s alright with you.
Best regards,
Pinker
the code you provided can start + restart the function perfectly, but for some reason it doesnt stop the function at task.cancel(thread)
1 Like
Okay that was just some roblox shenanigans. When you task.spawn
a coroutine, it’s state is never actually running but instead just suspended for some reason.
I’ve updated my code above to fix this problem.
Best regards,
Pinker
1 Like