Play Sound from Part and make it audible to the entire server

Hi. I’ve made a simple punch animation, hit detection with raycasting, and a corresponding sound effect. My objective is to simply play a 3D Sound from the Part returned as the raycast’s result so that the person who threw the punch and anyone nearby can hear it.

To accomplish this, I am trying to use Remote Events. My understanding of the Remote Event interaction in the code I’ve written is this:

  1. The local punch script and server script both access the ReplicatedStorage service to utilize
    soundEvent.
  2. The server script eventHandler instantiates a new Sound.
  3. Once the punch is detected to have hit something, soundEvent in the server script is fired with two
    parameters: the Part that the raycast hit and the punch sound ID.
  4. The server reacts to the firing of soundEvent by calling the playSound function, where it assigns the
    punch sound effect ID and parent Part to the previously instantiated Sound before playing it.

Local Script:

local ReplicatedStorage = game:GetService("ReplicatedStorage") -- Access server events
...
local soundEvent = ReplicatedStorage:WaitForChild("soundEvent") -- Get server-side event to play sounds when needed
...
local function onClick() -- Function to be executed when the local player clicks their left mouse button
	if not mouseClicked then -- Debounce
		mouseClicked = true
		-- Debounced code start
		punchTrack:Play() -- Play the punch animation
		punchConnection = punchTrack:GetMarkerReachedSignal("punch"):Connect(
			function() -- On the critical frame, start hit detection
				print("Detecting now.")
				local hitResult = hitDetect() -- Find out what the punch hit, if anything
				if hitResult ~= nil then
					soundEvent:FireServer(hitResult.Instance,"10859901757") 
                                        -- Tell server to play punch sound effect from impacted part
					if hitResult.Instance.Parent:FindFirstChild("Humanoid") then
						-- do server-side code to damage player
					end
				end
			end)
		wait(1.5) -- Let the animation finish + slight cooldown
		punchConnection:Disconnect()
		-- Debounced code end
		mouseClicked = false
	end
end

playerMouse.Button1Up:Connect(onClick)

Server Script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local soundEvent = ReplicatedStorage:WaitForChild("soundEvent")
local sound = Instance.new("Sound")

local function playSound(player,part,id)
	sound.SoundId = "rbxassetid://" .. id
	sound.Parent = part
	sound:Play()
end

soundEvent.OnServerEvent:Connect(playSound)

Notes:
1. The RemoteEvent in ReplicatedStorage is named soundEvent.
2. The part passed to playSound is always in workspace

However, the issue is that the sound still only plays for the player who threw the punch. It’s a 3D sound, all right, but nobody else can hear it.

I thought this to be a really simple, quick task. But I’ve exhausted the resources available in search of a definitive answer and find conflicting information. Some people say you’d need to fire a separate event to every single client; some people say you wouldn’t. Some people say just playing the sound server-side (which is what I believe I am doing here) is good enough, some people say it’s not.

I’ve tried setting RespectFilteringEnabled to false (yes, knowing that it’s a bad idea), manually toggling Sound.Playing to true (even though :Play() should already do that), hard-coding the Sound’s properties into the server script (thinking, “maybe the sound clip is so short that other clients just don’t have the time to load it before it’s already over”), and finally caving by using FireAllClients (which I didn’t want to use because I felt I could do without it, but, to my surprise, didn’t work anyway)

Alternative Server Script implementing FireAllClients:

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local soundEvent = ReplicatedStorage:WaitForChild("soundEvent")
local soundEventBroadcast = ReplicatedStorage:WaitForChild("soundEventBroadcast")

local function playSound(player,part,id)
	soundEventBroadcast:FireAllClients(part,id)
end

soundEvent.OnServerEvent:Connect(playSound)

New Event-Handling Local Script implementing FireAllClients:

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local soundEventReceiver = ReplicatedStorage:WaitForChild("soundEventBroadcast")

local sound = Instance.new("Sound")
local function playSound(part,id)
	sound.SoundId = "rbxassetid://" .. id
	sound.Parent = part
	sound:Play()
end

soundEventReceiver.OnClientEvent:Connect(playSound)

Notes:
1. The original Local Script in this implementation is unchanged
2. The name of the new event in this implementation from Server to Client is soundEventBroadcast

So, at this point, I have to think there’s a big, obvious thing that I’m just glossing over.

I don’t have time to read through your full post but I think you may find this interesting and helpful:

https://developer.roblox.com/en-us/onboarding/in-game-sounds/1

1 Like

Appreciate the reply. I just tried to use SoundService instead of constructing the asset ID through parameters and the result was the same – initiating client can hear the sound, others cannot.

1 Like

Wondering if maybe this is a basic file system issue? serverEventHandler under SeverScriptService is the server code, punch under StarterCharacterScripts is the local code.

195127984e7b0d0f4f4472f79377eb3e

Had time to investigate this again, and after noticing that a second client does have the sound clip in their workspace after being created by the first client, then testing with a longer sound clip, I realized what was going on – believe me, it’s stupid.

I didn’t realize that, when you instantiate a local server test with multiple clients from Studio, Studio automatically mutes all the other client windows except the one you currently have selected. So I would use one client to punch something while muting its window, and had the false impression that I would hear the sound coming from the second client even though I had selected the first client’s window to punch and make the noise. Because the punch sound was so short, I never realized that the sound had in fact played and that the second client window was just muted automatically.

It just goes to show that often when you have a problem in programming that seems impossible, you’ve overlooked something completely obvious that was staring you right in the face the whole time.

2 Likes