Trying to make typewriter effect, but typewriter sound seems to play twice

I’m making a script that reveals a message one character at a time and plays a typewriter sound at a slightly randomized pitch with each character revealed.
This is the script:

local TextLabel = script.Parent
local Button = game.Players.LocalPlayer.PlayerGui:WaitForChild("ScreenGui").OptionYes
local message = "So, this is the place Joey told me about..." -- put your full message here
local message2 = "This old building is the perfect place to host something of value." -- put your full message here
local message3 = "Now it's time to open these rusted doors and hopefully find something worth my time." -- put your full message here
local message4 = "What is this place?..." -- put your full message here
local message5 = "..." -- put your full message here
local message6 = "The door is gone." -- put your full message here
local message7 = "I need to find some way out of here." -- put your full message here
local Audio = game.ReplicatedStorage.TypeWriter

local function StartNewGame()
	task.wait(5)
	for i = 1, #message, 1 do
		local CloneAudio = Audio:Clone()
		local PS = CloneAudio:FindFirstChildOfClass("PitchShiftSoundEffect")
		PS.Octave = math.random(95, 105)/100
		CloneAudio.Parent = game.SoundService
		TextLabel.Text = string.sub(message, 1, i)
		CloneAudio:Play()
		CloneAudio.Ended:Connect(function()
			CloneAudio:Destroy()
		end)
		task.wait(0.08)
	end
	task.wait(3)
	for i = 1, #message2, 1 do
		local CloneAudio = Audio:Clone()
		local PS = CloneAudio:FindFirstChildOfClass("PitchShiftSoundEffect")
		PS.Octave = math.random(95, 105)/100
		CloneAudio.Parent = game.SoundService
		TextLabel.Text = string.sub(message2, 1, i)
		CloneAudio:Play()
		CloneAudio.Ended:Connect(function()
			CloneAudio:Destroy()
		end)
		task.wait(0.08)
	end
	task.wait(3)
	for i = 1, #message3, 1 do
		local CloneAudio = Audio:Clone()
		local PS = CloneAudio:FindFirstChildOfClass("PitchShiftSoundEffect")
		PS.Octave = math.random(95, 105)/100
		CloneAudio.Parent = game.SoundService
		TextLabel.Text = string.sub(message3, 1, i)
		CloneAudio:Play()
		CloneAudio.Ended:Connect(function()
			CloneAudio:Destroy()
		end)
		task.wait(0.08)
	end
	task.wait(3)
	TextLabel.Visible = false
	task.wait(8)
	TextLabel.Visible = true
	for i = 1, #message4, 1 do
		local CloneAudio = Audio:Clone()
		local PS = CloneAudio:FindFirstChildOfClass("PitchShiftSoundEffect")
		PS.Octave = math.random(95, 105)/100
		CloneAudio.Parent = game.SoundService
		TextLabel.Text = string.sub(message4, 1, i)
		CloneAudio:Play()
		CloneAudio.Ended:Connect(function()
			CloneAudio:Destroy()
		end)
		task.wait(0.08)
	end
	task.wait(3)
	for i = 1, #message5, 1 do
		local CloneAudio = Audio:Clone()
		local PS = CloneAudio:FindFirstChildOfClass("PitchShiftSoundEffect")
		PS.Octave = math.random(95, 105)/100
		CloneAudio.Parent = game.SoundService
		TextLabel.Text = string.sub(message5, 1, i)
		CloneAudio:Play()
		CloneAudio.Ended:Connect(function()
			CloneAudio:Destroy()
		end)
		task.wait(1)
	end
	task.wait(3)
	for i = 1, #message6, 1 do
		local CloneAudio = Audio:Clone()
		local PS = CloneAudio:FindFirstChildOfClass("PitchShiftSoundEffect")
		PS.Octave = math.random(95, 105)/100
		CloneAudio.Parent = game.SoundService
		TextLabel.Text = string.sub(message6, 1, i)
		CloneAudio:Play()
		CloneAudio.Ended:Connect(function()
			CloneAudio:Destroy()
		end)
		task.wait(0.08)
	end
	task.wait(3)
	for i = 1, #message7, 1 do
		local CloneAudio = Audio:Clone()
		local PS = CloneAudio:FindFirstChildOfClass("PitchShiftSoundEffect")
		PS.Octave = math.random(95, 105)/100
		CloneAudio.Parent = game.SoundService
		TextLabel.Text = string.sub(message7, 1, i)
		CloneAudio:Play()
		CloneAudio.Ended:Connect(function()
			CloneAudio:Destroy()
		end)
		task.wait(0.08)
	end
	task.wait(3)
	TextLabel.Visible = false
end

Button.MouseButton1Click:Connect(StartNewGame)

If I change local Button = game.Players.LocalPlayer.PlayerGui:WaitForChild("ScreenGui").OptionYes to local Button = game.Players.LocalPlayer.PlayerGui.ScreenGui.OptionYes it outputs an error, but works, at least in Roblox Studio. When I play the game on Roblox, the audio bugs and plays twice at once when it shouldn’t. Seriously the amount of differences between Roblox and Roblox Studio can make it so difficult to playtest a game.

Is there any way I can stop the audio from playing twice?

2 Likes

Is the Audio.PlayOnRemove property enabled? If so, when you are destroying the Sound it would play a second time.

image

1 Like

It’s set to false. The audio plays twice at the same time, and if PlayOnRemove was set to true, this would be out of sync anyways. The only idea I have is that maybe the local script is being duplicated, sort of like how each player has their own GUI. Is it possible that the local script could be getting duplicated so it plays the audio twice?
The original audio is in ReplicatedStorage, and the clone audios are in SoundService, if that has any importance.

Have you tried the simple route of just adding a debounce? Doing so won’t solve the underlying issue but will still serve as a working solution at least temporarily.

Edit 1: Also I would recommend you make sure there is no accidental duplication on either end either with the button or the script itself as well as any possible other scripts interfering or calling the same trigger on the mouse click.

Edit 2: Also did you check if it’s looped?

Edit 3: Also try Button.MouseButton1Click:DisconnectAll() to make sure any other possible accidental connections are severed

(I haven’t read it fully yet so if I see the actual problem I will edit this)

2 Likes

I changed the first part of the script to this:

local TextLabel = script.Parent
local Button = game.Players.LocalPlayer.PlayerGui:WaitForChild("ScreenGui").OptionYes
local message = "So, this is the place Joey told me about..." -- put your full message here
local message2 = "This old building is the perfect place to host something of value." -- put your full message here
local message3 = "Now it's time to open these rusted doors and hopefully find something worth my time." -- put your full message here
local message4 = "What is this place?..." -- put your full message here
local message5 = "..." -- put your full message here
local message6 = "The door is gone." -- put your full message here
local message7 = "I need to find some way out of here." -- put your full message here
local Audio = game.ReplicatedStorage.TypeWriter

local function StartNewGame()
	task.wait(5)
	for i = 1, #message, 1 do
		local CloneAudio = Audio:Clone()
		local PS = CloneAudio:FindFirstChildOfClass("PitchShiftSoundEffect")
		PS.Octave = math.random(95, 105)/100
		CloneAudio.Parent = game.SoundService
		TextLabel.Text = string.sub(message, 1, i)
		CloneAudio:Play()
		print(i)
		CloneAudio.Ended:Connect(function()
			CloneAudio:Destroy()
		end)
		task.wait(0.08)
	end

It prints each number twice, which means that part of the script is being ran more than once. The script is being duplicated in the player’s PlayerGui.

I added this at the end:

if script.Parent.Parent.Parent.Name == "StarterGui" then
	script:Destroy()
end

I thought it might work, but each number was still being printed twice.

Have you tried adding a debounce as Mocha had suggested? If that part of the script is being run more than once then that should fix the issue. If it doesn’t then the script is probably being duplicated still.

1 Like

If your local script is under StarterGui it will be duplicated into PlayerGui, meaning you will have two scripts running at the same time, a simple fix is moving the local script somewhere else, like StarterPlayerScripts under StarterPlayer where it won’t be duplicated.

1 Like