Halting a text writing mechanism

I have a system to write a text onto a TextLabel in an amount of time, but this can be called mutliple times.
If one is called at the same time as another then they’ll both write at the same time.

I’ve been trying to find a way to halt the ongoing writing but I can’t really figure out how.
This is the code I’ve been using:

local function titleWriteAsync(text, timeToWrite)
    coroutine.wrap(function()
        local interval = timeToWrite/#text
        Title.Text = ""
        for i = 1, #text do
            Title.Text = Title.Text .. string.sub(text, i, i)
            wait(interval)
        end
    end)()
end

I did have a boolean “isWriting” and it’d wait until the other has finished, but that isn’t what I’m trying to achieve.

Any suggestions are as always greatly appreciated.

6 Likes

So like a qued text system? If so it’d be done like this:
This probably won’t work, but give it a try?

local cue = {};
local writing = false;
local function titleWriteAsync(text, timeToWrite)
    if writing == false then
        writing = true;
        coroutine.wrap(function()
            local interval = timeToWrite/#text
            Title.Text = ""
            for i = 1, #text do
                Title.Text = Title.Text .. string.sub(text, i, i)
                wait(interval)
            end

            if #cue !== 0 then
                titleWriteAsync(cue[1][1], cue[1][2]);
                table.remove(cue, 1)
            end
        end)()

    else

        table.insert(cue, {text, timeToWrite})


    end
end
1 Like

I’m trying to stop the Text writing, not cue it.

Try using an if statement with a break.

Yeah but I’m not certain how I can implement the boolean here.

Is there a precise text you want it to write,

Well yeah, I call it like titleWriteAsync("Badges", 0.5)

This is a good opportunity for the gods to look down upon my makeshift approach for overriding simple synchronous operations. If anyone knows of a better way, I want to hear it for sure.

For this particular response, I will be encapsulating some of the data into a Writer function. It doesn’t add much complexity, but it permits the flexibility of multiple text writers. You can pull it out of the function if you dislike the approach.

Finally, the overriding centers around the writerequest and thisrequest variables. thisrequest is created once you begin to write, and is compared to writerequest every time you’re about to write something. Anyways,

local Title = script.Parent

local function createTextWriter(TextObj)
	local writerequest = 0
	
	local function write(Text,TimeToWrite)
		writerequest = writerequest + 1 --update currrent writer. Will likely never exceed 1.7 × 10^308
		local thisrequest = writerequest 
		
		local interval = TimeToWrite/#Text
        TextObj.Text = ""

		spawn(function()
	        for i = 1, #Text do
				 if thisrequest ~= writerequest then return end --if something updated writerequest, don't perform
				
	            TextObj.Text = TextObj.Text .. string.sub(Text, i, i)
	            wait(interval)
	        end
		end)
	end
	
	--return the writing function
	return write
end


wait(2) --for testing purposes, so I can see the results when I join studio
local TitleTextWriter = createTextWriter(Title) --create a TextWriter for this object

TitleTextWriter("Hello sir.",2) --set that text
wait(0.5) --delay to show overriding
TitleTextWriter("ehdwayhdwaiuhdaw",2) --set that text

4 Likes

I’ve been experimenting, and I ended up with this code, which of course can be optimized and rewritten.

Code
local label = script.Parent.TextLabel;
local current;

local function typeAsync (text, duration)
		
	local function run ()
		local current;
		local interval = duration / #text;
		local i = 0;
		local active = true;
		
		coroutine.resume(coroutine.create(function () 
			label.Text = "";
	
			while active and (i < #text) do
				i = i + 1;
				label.Text = label.Text .. text:sub(i, i);
				wait(interval)
			end
			
			print("DONE")
		end))
		
		return function () 
			active = false;
		end
	end
	
	-- If there is a current process of typing, stop it
	if current then
		current() -- This will set "active" to false in the function's scope
	end
	
	current = run() -- Now, run the "new" function
	return current; -- Return current, so they can also stop it
end

-- // Checking if it properly "override" the flow
wait(1)
local a = typeAsync("hello", 1)
wait(.25)
typeAsync("Bye bye", 1)
wait(2)

-- // Checking if you can stop it
local a = typeAsync("time for test", 2);
wait(1)
a();

Place: Baseplate.rbxl (20.1 KB)

1 Like

Thank you a ton @WoolHat & @1TheNoobestNoob; your method was pretty great Noob however Wool’s seemingly works much faster hence why I’ve given the solution.

2 Likes