Why isn't this coroutine yielding?

I have a coroutine that moves a target on a remote event, which is triggered by InputBegan and InputEnded. Those trigger just fine, and anything I have them trigger works. The problem is, I want to yield a coroutine. If anyone has any idea why the coroutine doesn’t end I would appreciate it. Thank you!
Local script:

uis.InputBegan:Connect(function(input)
	if not Choking then return end
	if input.KeyCode == Enum.KeyCode.A then
		game.ReplicatedStorage.ChokeA:FireServer(eHum,true)
	end
end)
uis.InputEnded:Connect(function(input)
	if not Choking then return end
	if input.KeyCode == Enum.KeyCode.A then
		game.ReplicatedStorage.ChokeA:FireServer(eHum,false)
	end
end)

ServerScript

local a = coroutine.create(function()
	while wait(0.01) do
		eHrp.CFrame = eHrp.CFrame*CFrame.new(0.1, 0, 0)		
	end
end)

game.ReplicatedStorage.ChokeA.OnServerEvent:Connect(function(plr, eHum, b)
	if b == true then
		coroutine.resume(a)
	else
		coroutine.yield(a)
	end
end)

you could try changing a global value that is hooked up to a while true and if statement upon receiving b

1 Like

Coroutines are not yielded from the outside, and coroutine.yield doesn’t accept a coroutine to yield as an argument. It has to be called from inside of the thread.

coroutine.yield(args: Tuple): Tuple

→ suspends the execution; passes the args as additional params to resume.

Read more in the appended article: coroutine | Documentation - Roblox Creator Hub.


Lua is single-threaded. The task scheduler takes care of the resumption. That applies to Serial Luau (not Parallel Luau and real multi-threading, which is part of another story). Only one coroutine is resumed at a time. That results in an attempt to yield an already yielded coroutine.

Technically, you can use coroutine.close() (or the task library counterpart task.cancel()) to close the whole thread.

However, :Connect() and :Once() already run the code in a delegated green thread, and coroutines have access to variables outside of the scope.

Therefore, it’s better to follow @Exozorcus’s idea about an external variable. Perhaps you should also consider using a tween.

1 Like

I want the part to move while the player is holding down, and stop when the player stops holding. How do you suppose I could do that without a coroutine or a loop? Thanks for your help so far!

You can maybe try to do something like this :

local CanMove = false

local function Move()
	while CanMove == true do
		eHrp.CFrame = eHrp.CFrame*CFrame.new(0.1, 0, 0)		
		task.wait(0.01)
	end
end

game.ReplicatedStorage.ChokeA.OnServerEvent:Connect(function(plr, eHum, b)
	if b == true then
		CanMove = true
		Move()
	else
		CanMove = false
	end
end)
2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.