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 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.
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.