I’m trying to play a sound once to the local player when they touch a part. But my problem is that when I touch the part, it will play, but if I stand on the part, the song will keep playing the beginning of the song, until I leave it. I also want to destroy the sound later when they touch a separate part. But how do I solve this? This was the script:
local CanTouch = true
script.Parent.Touched:connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
if not player.PlayerGui:FindFirstChild("SoundEffect") then
local sound = script.Parent.Sound:Clone()
sound.Name = "SoundEffect"
sound.Parent = player.PlayerGui
sound:Play()
script.parent.CanTouch = false
wait(1)
script.parent.CanTouch = true
elseif player.PlayerGui:FindFirstChild("SoundEffect") then
local Sound = player.PlayerGui:FindFirstChild("SoundEffect")
Sound:Destroy()
end
end
end)
Hi,
your issue is that the sound gets played, then destroyed again and created and played again and this in a loop because the onTouch function fires all time you are standing on the part. When do you want to exactly destroy the sound again?
So here you have a part when if you touch it, it will play the sound and one that will delete the sound. If the sound ended to play, it can be played again with touching the part again. Does that help?
local CanTouch = true
playing = false
script.Parent.Touched:connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
if not player.PlayerGui:FindFirstChild("SoundEffect") and playing == false then
playing = true
local sound = script.Parent.Sound:Clone()
sound.Name = "SoundEffect"
sound.Parent = player.PlayerGui
sound:Play()
script.parent.CanTouch = false
wait(1)
script.parent.CanTouch = true
end
end
end)
SoundDeletePart.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
if game.StarterGui:FindFirstChild("SoundEffect") then
game.StarterGui:FindFirstChild("SoundEffect"):Destroy()
playing = false
end
end
end)
game.StarterGui:FindFirstChild("SoundEffect").Ended:Connect(function()
playing = false
end)
Your script was broken too, sorry. Your script played the sound, got rid of it when I touched the part, but when I went back to play the sound again, it wouldn’t let me. I tried to modify the script, and now when I touch the part, it clones it so many times that it lags the game. Here was my script:
local CanTouch = true
while true do
wait()
script.Parent.Touched:connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
if not player.PlayerGui:FindFirstChild("SoundEffect") then
local sound = script.Parent.Sound:Clone()
sound.Name = "SoundEffect"
sound.Parent = player.PlayerGui
sound:Play()
wait(1)
elseif player.PlayerGui:FindFirstChild("SoundEffect") then
local sound = script.Parent.Sound:Clone()
if sound.Playing == false then
wait(1)
sound.Parent = player.PlayerGui
sound.Playing = true
end
end
end
end)
end
Here’s something that might work, although I have not tested it.
-- Play a sound on touch then destroy the sound on a different part
local CanTouch = true
script.Parent.Touched:Connect(function(hit)
-- Check if the player exists and if the player already stepped on the part
if hit.Parent:FindFirstChild("Humanoid") and CanTouch == true then
CanTouch = false
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
-- if the player does not have the sound, clone and play it
if not player.PlayerGui:FindFirstChild("SoundEffect") then
local sound = script.Parent.Sound:Clone()
sound.Name = "SoundEffect"
sound.Parent = player.PlayerGui
sound:Play()
else -- otherwise delete it
player.PlayerGui:FindFirstChild("SoundEffect"):Destroy()
end
task.wait(1)
CanTouch = true
end
end)
Or you could just set the value to true, check the distance by looping it and automatically set it false if player is too distanced again.
If you want to detect if they touch another part, then you should save the last saved part and check if the most recent touched part is the same as the new one. Like:
`local Part`
Touched:Connect(function(Hit)
if not Part then
Part = Hit.Parent
elseif (Part ~= Hit.Parent)
-- Touched a different part!
end
end)
Ah i see ok then here is a script that works if you haven’t fixed the issue yet.
script.Parent.Touched:connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
if not player.PlayerGui:FindFirstChild("SoundEffect") then
-------- If the player doesn't have the sound then create it and play it-----
local sound = script.Parent.Sound:Clone()
sound.Name = "SoundEffect"
sound.Parent = player.PlayerGui
sound:Play()
end
end
end)
script.Parent.TouchEnded:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
-------------- When a part of a player leaves the music pad it checks if other parts..
-- of his body are still touching the pad --------------
local stilltouching = false
for i,v in script.Parent:GetTouchingParts() do
if v.Parent == hit.Parent then stilltouching = true end
end
--------------- If no other part of the player is touching the pad, that means he fully..
-- left it,so then you destroy the sound --------------
if not stilltouching then
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
if player.PlayerGui:FindFirstChild("SoundEffect") then
local sound = player.PlayerGui["SoundEffect"]
sound:Destroy()
end
end
end
end)
It works and doesn’t work at the same time. When I walk into the part, it plays, and when I walk out, it stops play. That part was good, but some times it wouldn’t play the part, and some times it would. What is wrong with the code?
After some testing you’re actually right it doesn’t work very well. So i changed some things and now it works 99% as intended.
First turn the touch detection part into a region with CanCollide set to false and Transparency set to 1 the part should be as high as the player knees as in the picture below
Now use this script instead
script.Parent.Touched:connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
if not player.PlayerGui:FindFirstChild("SoundEffect") then
-------- If the player doesn't have the sound then create it and play it-----
local sound = script.Parent.Sound:Clone()
sound.Name = "SoundEffect"
sound.Parent = player.PlayerGui
sound:Play()
end
end
end)
script.Parent.TouchEnded:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
------------ If any part of the player leaves the region remove the sound -------
if player.PlayerGui:FindFirstChild("SoundEffect") then
local sound = player.PlayerGui["SoundEffect"]
sound:Destroy()
end
end
end)
And finally, add the pad under the region (the one i had in red)
All you do is copy and paste this exact same script into two different parts.
You touch part A → receive a sound → play it
You touch part B → you already have a sound → delete it
The above scenario also applies by touching the same part twice, however there is a debounce variable “CanTouch” which prevents that from happening for x second(s).