Is there another way to make sound play in sync with a typewriter effect?

Basically, I made a script (shown below) that DOES work as intended…for the most part. I have another script managing a typewriter effect on a text UI and this script simply syncs a sound effect each time another character appears on the UI. This script does work, but it causes sounds to be created and destroyed A LOT. This results in lag. What I’m aiming for is another way to do this where I won’t have to spam create and destroy sound instances. Anyone know how to do this?

script.Parent.TextLabel.Changed:Connect(function(property)
	if property == "MaxVisibleGraphemes" then
		local sound = script.Sound:Clone()
		sound.Parent = game.Workspace
		sound:Play()
		sound.Ended:Wait()
		sound:Destroy()
end
end)

Why do you need to clone the sound everytime you use it, why not just store it once and play it when needed?

1 Like

Instead of listening for changes to MaxVisibleGraphemes, could you not :Play() the sound within the same loop that’s incrementing graphemes?

Well…I already tried doing that and this is the solution I came to AFTER doing that. The single sound can’t keep up with the rate of the text changes.

ok why not try this code then, since the script is for ui i presume the sound only needs to be played locally

local ss = game:GetService("SoundService")
script.Parent.TextLabel:GetPropertyChangedSignal("MaxVisibleGraphemes"):Connect(function()
	ss:PlayLocalSound(script.Sound)
end)
1 Like

Unfortunately, I can’t. The script bugs out and the entire typewriter effect glitches and just makes the entire string of text appear. Even if this didn’t happen, I’d have to result to the cloning strategy once again since I can’t mass play the audio.

You can spam :Play() an audio as fast as you want, you’d just need to make the sound last as long as the delay between incrementing the graphemes for it to sound good. Could you share a snippet of the code you’re using for the typewriter effect? Cloning is an ineffective solution that shouldn’t be necessary.

local index = 0
	for first, last in utf8.graphemes(displayText) do
		index = index + 1
		guiObject.MaxVisibleGraphemes = index
		wait(delayBetweenChars)
	end 

This is the main part that manages the text. All it does is increase the max graphemes repeatedly. The actual sound is a mere 0.186 seconds. My attempt to make the sound play repeatedly was putting sound:Play() right after the part where it adds 1 to the index value. Am I doing something wrong?

Have you tried my script? it plays the sound the instant the property changes without having to clone the sound at all

I’ve recreated it using a similarly short sound, and this works just fine. I used the sounds’ length as the delayBetweenChars, could yours have been so short you didn’t hear the sound?
This is a LocalScript parented to a textlabel, with the sound parented to the script.

local guiObject = script.Parent
local displayText = script.Parent.Text
local delayBetweenChars = script.sound.TimeLength
local index = 0

for first, last in utf8.graphemes(displayText) do
	index = index + 1
	guiObject.MaxVisibleGraphemes = index
	script.sound:Play()
	task.wait(delayBetweenChars)
end 
1 Like

Thank you, this worked. However, I needed to change some key aspects of the scripts in order to do this. It works for now, so I’ll mark this as a solution.

Also thank you for your efforts. I believe your script might’ve worked as well. Can’t mark two things as a solution, so here’s a like. (I did however temporarily mark yours as a solution, but I’m not certain it’ll affect your total amount of solutions.)

1 Like