Why does Destroy() cancel my coroutine?

Hi guys! My name is Adrian, I’m from Sweden and started developing in Roblox 31st of May 2023. This morning I ran into a very special issue that I hope someone with more experience than me can shine some light on.

I have two scenarios:

  • One where I start a coroutine, and afterwards destroy a frame.
  • One where I destroy a frame, and afterwards start a coroutine.

If the frame is destroyed after starting the coroutine, then the coroutine will stop running on this line: task.wait(1)

I’ve uploaded 3 videos showcasing my issue:
Video1
Video2
Video3

CODE

Coroutine:

local function acceptTradeDelayCoroutine()
	print("Coroutine Ran!")
	local run = true
	while run == true do
		print("Coroutine Iteration!")
		print("acceptTradeDelay: " .. tostring(acceptTradeDelay))
		task.wait(1)
		acceptTradeDelay = acceptTradeDelay - 1
		print("acceptTradeDelay2: " .. tostring(acceptTradeDelay))
		if acceptTradeDelay == 0 then
			print("Coroutine Last Iteration!")
			tradeDelayCoroutineActive = false
			acceptTradeFrame.AcceptText.Text = "Accept"
			acceptTradeFrame.InterractionScript.Enabled = true
			acceptTradeFrame.BackgroundColor3 = Color3.new(174/255, 255/255, 178/255)
			run = false
		else
			acceptTradeFrame.AcceptText.Text = tostring(acceptTradeDelay)
		end
		print(run)
	end
	print("end")
end

Starting the coroutine:

module.InitAcceptTradeDelay = function()
	print("Coroutine will run soon!")
	print(tradeDelayCoroutineActive)
	acceptTradeDelay = 10
	acceptTradeFrame.BackgroundColor3 = Color3.new(127/255, 127/255, 127/255)
	acceptTradeFrame.AcceptText.Text = tostring(acceptTradeDelay)
	acceptTradeFrame.InterractionScript.Enabled = false
	if tradeDelayCoroutineActive == false then
		print("tradeDelayCoroutineActive was false!")
		tradeDelayCoroutineActive = true
		local tradeCoroutine = coroutine.create(acceptTradeDelayCoroutine)
		coroutine.resume(tradeCoroutine)
	end
end

Undo accept trade code:

local function undoAcceptTrade()
	module.InitAcceptTradeDelay()
	local offerTradeAcceptedText = tradingUi.TradingWindow.OfferWindow.TradeAcceptedText
	offerTradeAcceptedText.Visible = false
	local offerFrame = tradingUi.TradingWindow.OfferWindow
	offerFrame.BackgroundTransparency = 1
	
	local receiveTradeAcceptedText = tradingUi.TradingWindow.Receive.TradeAcceptedText
	receiveTradeAcceptedText.Visible = false
	local receiveFrame = tradingUi.TradingWindow.Receive
	receiveFrame.BackgroundTransparency = 1
end

Remove offered item code (WORKING):

module.RemoveOfferItemFromTradeWindow = function(frame, itemSlot)
	-- Restore state
	module.removeItemsActive = false
	for _, foundFrame in pairs(offerScrollingFrame:GetChildren()) do
		if foundFrame.Name == "TradeStopRemoveItem" then
			foundFrame:Destroy()
			break
		end
	end
	local tradeRemoveItemFrame = replicatedStorage.GUI.TradeRemoveItem
	local cloneTradeRemoveItemFrame = tradeRemoveItemFrame:Clone()
	cloneTradeRemoveItemFrame.Parent = offerScrollingFrame

	-- Remove item from offer
	local result = removeItemFromOffer:InvokeServer(itemSlot)
	if result == "Success!" then
		-- Manipulate offer UI.
		frame:Destroy()
		-- We only need to undo if Success.
		undoAcceptTrade()
		-- Hide inspect screen since the hover-left event is gone with the frame object.
		inspectScreen.Visible = false
		--_G.SoundController.PlaySound(soundList.UI_Select9, 0.1, 1, true)		
	elseif result == "Error!" then
		-- Tried to remove an item from offer that had not been offered.
	end
end

If I switch the code in module.RemoveOfferItemFromTradeWindow = function(frame, itemSlot) to look like this instead, the code stops running at the task.wait(1) line inside the coroutine.

-- We only need to undo if Success.
undoAcceptTrade()
-- Manipulate offer UI.
frame:Destroy()

Thank you for reading, hope you have a great holiday whichever way you prefer to spend it :slight_smile:

Bump! :slight_smile: (I must type a certain amount of character, but I am not allowed to type the amount of characters?)