How would I have this sound play once when you are in range, then stop when you are out of range?

I’m trying to make for my door script, where when you come close to the door a sound plays, and a gui pops up. I got everything working, however I cannot get this to work.

I’ve noticed the issue is mainly that its probably playing then stopping immediately

I haven’t tried much solutions except adding a debounce or some other things.

Here is the local script, (I only want the sound to play for the client, that’s the reason.):

  ```	local mag2 = (Character.HumanoidRootPart.Position - Door.Center.Position).magnitude
	if mag2 <= Door.Config.Range.Value then
		if not played then
		sound:Play()
		wait(0.1)
		played = true
	if played == true then
		sound:Stop()
		played = false
		end
		end
	end ```
2 Likes

What I think is happening is it does not have time for the sound to play. You are only waiting 0.1 seconds. You could use wait(sound.TimeLength). This would wait the entire length of the song. Or, a method you probably would not want to use because it is not a good idea. You can do

spawn(function()
     repeat game:GetService("RunService").Heartbeat:Wait() until sound.Playing == false
     return
end)

This should wait for the sound to finish before it continues. :smiley:

wait will yield the script for .1 seconds, and sets played to true, then after .1s roblox resumes the script at the point it yielded at. It goes to the next if → if (playd == true) which it is, and stops the sound. This is why it stops so quickly.

Unless I’m misunderstanding your problem, you should be able to use the MaxDistance property, Sound | Documentation - Roblox Creator Hub

3 Likes

Sound plays once when in range but stops when you’re out of it? I think you’ve got the logic for the code wrong, since none of this is necessary. The only thing you need to know how to do is detect when the character is in range and make use of (^) Sound.MaxDistance.

Have you tried using an invisible/non-colliding part with Part.Touched?

I use this for a lot of things, like triggering dialogues, auto-opening doors, starting cutscenes, etc. It’s a lot simpler than looping to see if the player is within a certain distance (however you may want to use the aforementioned for certain things, like a light getting brighter as a player approaches).

I can’t really do any testing for this so sorry if I’m wrong, but you can add a part to the parent if this sound and get the position of the part and check if the player is in the radius, something like this:

local part = workspace.SoundPart -- assuming the parts parent is workspace.
local sound = part.Sound -- the sound
local runService = game:GetService("RunService")
repeat wait() until game.Players.LocalPlayer.Character
local player = game.Players.LocalPlayer.Character:WaitForChild("Torso") --[[ assuming this is a localscript
 use game.Players.PlayerAdded for server side.]]

runService.RenderStepped:Connect(function()
    if(not player.Position.x - part.Position.x <= sound.MaxDistance and not player.Position.y - part.Position.y <= sound.MaxDistance and not player.Position.y - part.Position.y <= sound.MaxDistance) then -- something like this could work
        sound:Play()
    else
        sound:Pause()
    end
end)

fixed any errors I made before, hope this helps!

Get the magnitude of the Vector3. Documentation: Vector3 | Documentation - Roblox Creator Hub

-- LocalScript
local runService = game:GetService("RenderService")
local player = game.Players.LocalPlayer
local soundPart = workspace:FindFirstChild("SoundPart")

while true do
    -- Get magnitude
    local magnitude = (player.Character.HumanoidRootPart.Position - soundPart.Position).Magnitude
    if(magnitude <= 50) then  -- 50 is the max distance that the HumanoidRootPart can stray from the SoundPart.
        sound:Play()
        wait(0.1)
        sound:Stop()
    end
    runService.RenderStepped:Wait() -- Wait for each frame to render.
end

That’s a simple solution, it should work pretty well. If you understand how it works, you should play around with it.

1 Like

An alternate method could be using a region3 along with workspace:FindPartsInRegion3()
Helpful links:

Also this module could be of use with that:

A slightly more reliable solution would be the use of the DistanceFromCharacter method of Players.

1 Like

Ah, never noticed that was a thing. I’ve only used magnitudes.