How to Pause/Resume code

Hi, I’m WatchaM3an.
I’m pretty new to the platform. And pretty bored.
I wanna make games, like pretty good games.

and what does every good game have…
you’ve guess it! A pause menu!

I started to search on the devforum and found multiple topics like this one.
But there was one big problem.

Roblox limitations make it difficult to actually pause scripts.

I had two expectations

  1. Make it universally applicable
    meaning it works with threads and task.spawn
  2. Make it actually pause and resume
    make it stop on the exact instruction it was about to do

anyway, I started with threads
I made a simple script

local yield = false;

coroutine.wrap(function()
	for i = 1, 5 do
		if yield then -- if the external thread makes `yield` equal true
			coroutine.yield(); -- it yields the thread
		end
		print(i)
		wait(1);
	end
end)()

wait(0.9); -- after 1 second (or close to one second), 
yield = true; -- it yields the cororutine on line. 6

there was 1 problem with this, it wasn’t really easy to apply.

this became a nightmare.
my second solution was signals

local yield = Instance.new('BindableEvent');

coroutine.wrap(function()
	yield.Event:Connect(coroutine.yield);
	for i = 1, 5 do
		print(i)
		wait(1);
	end
end)()

wait(0.9) -- yields it after one second
yield:Fire();

This provided an easy way to apply this into real games, if it worked.
There were now one more problem with this

When you fires the event, it DOES yield the thread, but not the right one.
It yields the external thread, but not the actual thread we want.

basically : coroutine.yield() == yield:Fire()

my third solution
a damn virtual machine

I used a interpreter that could interpret luau, which was important because roblox uses luau, not lua.

And I modifed it to actually pause and resume on each instruction. This works without interrupting the external thread, but can also be universally applied to other threads inside the actual thread.
It can literally pause and resume code.

All I need to do is pause tweens, animations…
i’m going to sleep :zzz:

2 Likes

I don’t particularly understand your question, it seems like you already found a solution. I am confused by your statement

When you fires the event, it DOES yield the thread, but not the right one.
It yields the external thread, but not the actual thread we want.

Are you saying that it yields the thread that makes the coroutine? And the coroutine still prints 1,2,3,4,5?

If the first solution works as a variable, why not instead of inputting the yield function in the signal, simply just make a variable at the top and change that variable to true inside the signal?

local yieldvar = false

coroutine.wrap(function()
	yield.Event:Connect(function() 
         yieldvar = true 
    end)
	for i = 1, 5 do
        if yieldvar then
			coroutine.yield()
		end
		print(i)
		task.wait(1);
	end
end)()

task.wait(0.9)
yield:Fire();

ok my bad i actually did a little more experimentation to understand your question. For regular signals, the connection actually is in a different thread

local yield = Instance.new('BindableEvent');
local currentThread = coroutine.running();

coroutine.wrap(function()
	local actualThread = coroutine.running(); -- The thread we want to yield

	yield.Event:Connect(function()
		local thread = coroutine.running();
		if currentThread == thread then
			warn("yielding external thread") 
		elseif currentThread == actualThread then
			warn('yielding correct thread')
		else
			warn('yielding a different thread?', thread)
		end

		coroutine.yield();
	end);

	for i = 1, 5 do -- what we want to pause
		print(i)
		wait(1);
	end
end)()

wait(0.9) -- yields it after one second
yield:Fire();

When it yields a different thread it doesn’t yield the correct thread, so yes it still prints 1, 2, 3, 4, 5

1 Like

Ok what I want to do is to create a system that pauses and resumes ANY code, yeah this does work but I want it to work universally (meaning threads inside threads will yield). Ultimately I already have a solution, but its been hard to make that work.

Yeah, I actually noticed in my code I made an error where I named the variable the same as the signal so make sure to fix that up. The one thing I hate about coroutines which I’ve always seemed to struggle with is proper thread control. It’s a shame I can’t just input a thread into coroutine.yield().

Unfortunately my solution is the best way, you’ll just have to implement more variables for each scope which you could then implement a table of them.