Coroutine.kill implementation

this is kind of late but i thought it was very interesting
after experimenting in this post
i noticed that script:Destroy() basically acts like coroutine.kill()~it GCs and everything
so is this the ultimate coroutine.kill()? and could it possibly be implemented into Roblox then since script:Destroy() already does it?
here is the test place I used: corouitnekill.rbxl (14.2 KB)

@AMD_chan I know this is very late lol but I also noticed that if you replace the wait(5) in the kill script with coroutine.yield() instead, the GC cleans up table t before the script is destroyed (since the script main thread has no references and isn’t running it gets GCed)

2 Likes

I remember playing around with this behavior a while back and facing some issues regarding the consistency at which the Lua threads get killed on :Destroy(); back then simply parenting the script to nil would disconnect all its connections and mess with some other stuff while leaving its main thread running, so I wouldn’t rely on the behavior.

if you can remember some of the things you did to break this behavior, I’d very much like to see

Edit: If you :Destroy() and set to nil inside of the script, the script will still run, but I think thats a special case because the (or a) script thread is still running

Edit 2: if a modulescript is destroyed from an outside script then the code will still run : (

1 Like

I think this could help you. @FieryEvent already said this but I think you were looking for this though.

shared.FunTables = {}
shared.CreateKillableFun = function(foo)
    local index = tostring(foo)..#shared.FunTables
    local thread = coroutine.create(foo)
    coroutine.resume(thread)
    shared.FunTables[index] = {foo,thread}
    return index,shared.FunTables[index][1]
end

shared.kill = function(Index, f)
    local env = getfenv(f)
    local thread = shared.FunTables[Index][2]
    function env:__index(k)
        if type(env[k]) == "function" and coroutine.running() == thread then
            return function()
                coroutine.yield()
            end
        else
            return env[k]
        end
    end
    setfenv(f, setmetatable({}, env))
    coroutine.resume(thread)
end-

this can go in the second script im guessing you can tell how to use it

local index,Funck = shared.CreateKillableFun(function()
    print("On")
    wait(1)
    print("Stopped?")
end)

wait(.1)
shared.kill(index, Funck)

It lets you stop a running function from outside the function.

2 Likes

Hi guys, I used the code offer by @FieryEvent (very thanks) to kill all the events “wait()” en LocalScript, but crash the memory :frowning: , What can I do to not crashing…?

local function foo()
while true do
wait(0.1)
print("working")   
end
end
local function kill(thread, f)
local env = getfenv(f)
function env:__index(k)
	if type(env[k]) == "function" and coroutine.running() == thread then
		return function()
			coroutine.yield()
			error("Killed " .. tostring(thread), 0)
		end
	else
		return env[k]
	end
end
setfenv(f, setmetatable({}, env))
coroutine.resume(thread)
 end
 local thread = coroutine.create(foo)
 coroutine.resume(thread)
 print(coroutine.status(thread)) --> suspended
 kill(thread, foo)
 wait(0.1)
 print(coroutine.status(thread)) --> dead    

My LocalScript execute 2 animations, and the crashing occurs when press the key “x” several times:

UIS.InputBegan:Connect(function(tecla,isTyping)
if tecla.KeyCode == Enum.KeyCode.X then		

	function kill(thread, f)
		local env = getfenv(f)
		function env:__index(k)
			if type(env[k]) == "function" and coroutine.running() == thread then
				return function()
					coroutine.yield()
					print("Killed " .. tostring(thread), 0)
				end
			else
				return env[k]
			end
		end
		setfenv(f, setmetatable({}, env))
		coroutine.resume(thread)
	end

	giro = true


	function animacion()
		solte = false
		Track1.Stopped:wait()

		if solte == false then

			Track2 = game.Players.LocalPlayer.Character.Humanoid:LoadAnimation(script.Holding)
			Track2:Play()			
			print("play track2")

			--********************************Inicio Remolino*******************************
			local function remolino()
				local remolino = script.remolino:Clone()
				print("Crea remolino")
				remolino.Parent = Character.UpperTorso
				remolino.CFrame = Character.UpperTorso.CFrame * CFrame.Angles(0.4,0,0) --porque? se crea chueco??

				remolino.Transparency = 1
				wait(0.5)
				remolino.Transparency = 0.5
				local remolino = Character.UpperTorso:FindFirstChild("remolino")

				spawn(function()
					print("antes de girar")
					while giro do
						print("girando")
							remolino.CFrame = remolino.CFrame * CFrame.Angles(0,0.5,0)
							wait()
					end
				end)
				spawn(function()
					while UIS:IsKeyDown(Enum.KeyCode.X) do
						print("apareciendo")
						remolino.Transparency -= 0.05
						wait()
					end	
				end)

			end	
			--********************************Fin Remolino**********************************

			--********************************Inicio Aura*******************************
			local function aura()

				local aura = game.ReplicatedStorage:WaitForChild("aura"):Clone()
				print("aura creada", aura)	

				local weld = Instance.new("Weld")
				weld.Parent = Character.HumanoidRootPart
				weld.Part0 = Character.HumanoidRootPart
				aura.CanCollide = false
				aura.Anchored = false
				aura.Parent = Character.HumanoidRootPart
				weld.Part1 = Character.HumanoidRootPart.aura
			end
			--********************************Fin Aura**********************************

			--********************************Inicio ShakeCamera**********************************
			local function shake()
				wait(0.7)

				while  UIS:IsKeyDown(Enum.KeyCode.X)  do

					local x = math.random(-10,20)/50
					local y = math.random(-10,20)/50
					local z = math.random(-10,20)/50

					Hum.CameraOffset = Vector3.new(x,y,z)
					wait()

				end
				Hum.CameraOffset = Vector3.new(0,0,0)				
			end
			--********************************Fin ShakeCamera**********************************

			spawn(aura)
			spawn(remolino)
			spawn(shake)
		end
	end
	local thread = coroutine.create(animacion)
	coroutine.resume(thread)
	local con
	con = tecla.Changed:Connect(function(prop)
		if prop == "UserInputState" then
			
			if Track2 then
				Track2:Stop()
				print("1 detuve Track2",Track2)
			end
			kill(thread, animacion)
 end
 end)
 end
 end)	

 UIS.InputEnded:Connect(function(tecla,isTyping)
 if tecla.KeyCode == Enum.KeyCode.X then
	solte = true
	print("solte",solte)

	if Track2 then
		Track2:Stop()
		print("2 detuve Track2",Track2)
	end
	--******************************** Inicio Desvanece y borra Remolino**************************************

	local remolino = Character.UpperTorso:FindFirstChild("remolino")
	if remolino then
		spawn(function()
			while true do 

				remolino.Transparency += 0.1
				wait()
			end							
		end)
		wait(1)	
		remolino:Destroy()
		giro = false
	--******************************** Fin Desvanece y borra Remolino**************************************
	--******************************** Inicio borra Aura**************************************
		if Character.HumanoidRootPart:FindFirstChild("aura") then
			Character.HumanoidRootPart.aura:Destroy()
			Character.HumanoidRootPart.Weld:Destroy()
		end
	--******************************** Fin borra Aura**************************************
 end
 end 
 end)