Hello,
I have created a script which uses the typewriter effect, but stops it if a button is pressed again to immediately complete the text. Now that I’ve got it to work, it displays a error, which does not stop the script from continuing, though.
I’m not the best in scripting, so any optimizations in the code would also be appreciated!
-- values
local label = script.Parent.TextLabel
local button = script.Parent.TextButton
local running = false
local setText = "testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttest"
cor = nil
-- typewriter effect
local function typewriter(text)
for i = 1, #text do
label.Text = string.sub(text, 1, i)
wait(0.04)
end
end
button.MouseButton1Click:Connect(function()
if running then
-- complete text and close coroutine
label.Text = setText
coroutine.close(cor)
else
-- prevent coroutine from being re-ran, create and run coroutine
running = true
cor = coroutine.create(typewriter)
coroutine.resume(cor, setText)
end
end)
If you make the cor variable local you will be able to fire the coroutine every time the mousebutton is clicked. other than that adding a pcall to the corotine.resume will stop it from erroring in the console
I now used a more effective typewriter effect, which uses a while loop from this post, but the error still seems to be happening after I added a cancelled variable as condition for the while loop.
That’s how it currently looks like:
-- conversation values
local label = frame.text
local button = frame.click
local currentlyrunning = false
local cancelled = false
local cor = nil
local RunService = game:GetService"RunService"
local Heartbeat = RunService.Heartbeat
local setText = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789!.,?"
local GoalLength = #setText
local TimeToTake = GoalLength/30
local Accumulated = 0
-- typewriter effect
local function typewriter(text)
while TimeToTake > Accumulated and cancelled == false do
Accumulated += Heartbeat:Wait()
label.Text = string.sub(text,1,math.floor((Accumulated/TimeToTake)*GoalLength))
end
end
button.MouseButton1Click:Connect(function()
if currentlyrunning then
-- complete text and close coroutine
cancelled = true
label.Text = setText
coroutine.close(cor)
else
-- prevent coroutine from being re-ran, create and run coroutine
currentlyrunning = true
cor = coroutine.create(typewriter)
coroutine.resume(cor, setText)
end
end)
Unfortunately, I don’t think there’s a way to stop this. I have actually encountered this error myself before, and it’s quite silly to say the least as it’s not really useful at all, nor does it actually stop execution at all.
You can read up on my post if you’d like:
And also a similar post with pretty much the same issue:
As i mentioned in my first response, the problem is that your wait(), or heartbeat in this case; is trying to resume a thread that youve closed.
In the code youve shown, you should just stick with the cancelled variable, so remove the coroutine.close. The result will be the same and you wont get the error anymore.
There is a way to stop this error; it is to not close threads that are scheduled to be resumed at a later date. (Which is what wait, heartbeat, delay, etc do)