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:
- The local punch script and server script both access the ReplicatedStorage service to utilize
soundEvent. - The server script eventHandler instantiates a new Sound.
- 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. - 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.