Part playing music on Touch glitch

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?

When the local player touches another part

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

are these parts regions that you enter or you step on them

Its the one where you step on them.

did you tried debugging with print commands to see if the script gets their?

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)

Yes I have already! It sadly didn’t help too much with me

Your using script.parent.CanTouch = false
Instead of using your initialized Variable at the top local CanTouch = true

So, try to edit your script it by doing

CanTouch = false
task.wait(Duration)
CanTouch = true

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)

Sorry for the delay i forgot about this :sweat:

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?

I’m not sure, I tested the code and it works perfectly for me. Can you explain further what is going wrong

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
image

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)

I’m sorry, but it acted even worse. This time, it didn’t even play the sound at all

you’re doing it wrong then because there is no way it doesn’t work

Have you tried this yet?

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).