Sound effects played on the client causes heavy fps stuttering and lag

I’m facing a pretty major issue. The issue is, that I have a remote handler that handles the playing of the sound effects when queried by the server. When received, it should play the sound effects on the client. Which is what it does. However, my game is suffering heavily due to lag spikes, and fps jittering due to the remotehandler that handles client sound playing. I feel I’ve done everything possible to optimize this to the best of my ability. (caching, and what not)

function RemoteModule.PlaySound(requestedSound, parent, properties)
	if not requestedSound then return end

	properties = properties or {}

	local cachedSound = parent:FindFirstChild("S_"..requestedSound.SoundId)
	if not cachedSound then
		local soundClone = requestedSound:Clone()

		for property, value in pairs(properties) do
			soundClone[property] = value
		end
        soundClone.Name = "S_"..requestedSound.SoundId
		soundClone.Parent = parent
		soundClone.SoundGroup = game.SoundService.GlobalSounds
		soundClone:Play()
		print("played new sound")
	else
		for property, value in pairs(properties) do
			cachedSound[property] = value
		end
		cachedSound:Play()
		print("played cached sound")
	end
	

end 

These are some examples.
Example 1: Client sound playing enabled Watch 2026-08-14 23-38-59 | Streamable
Example 2: Client sound playing disabled (much more smoother) Watch 2026-08-14 23-39-52 | Streamable
(of course, there is the possbility that the problem comes from how im firing the remote from other scripts)

EDIT: I think the issue may have resolved itself? Ran a playtest with about 25-50 zombies and all went well. Just keeping this open for a little while longer though if there is an issue about how im optimizing soundplaying.

The Roblox engine is built in a way such that your network receive is greatly linked to the client’s FPS. The higher the network receive, the lower your FPS. I have no idea why…

In the clip you’ve shown, your network receive spikes to about 140KB/s initially, and then jumps around from 30KB/s to 200KB/s randomly, when going near the zombies, you don’t want your network receive to go even close to 50KB/s at any point in your game. I don’t think the issue is within your sound effect handler, but more so the amount of data you’re sending, be it either the data you’re sending for the sound effects, or some other game system entirely.

3 Likes

I’ll look into it :thinking:. I haven’t tried testing ingame compared to studio yet, so I’ll give an update on how much data is sent. Usually though, the main thing being sent is just the sound effects as per the script profiler says. Did this network issue stay the same during the playtest without sound playing?

1 Like

Heres what I got for the data putthrough during an ingame playtest (soundplaying was on, fps was jittery, and added much more zombies)

Same thing, soundplaying on, with a lesser amount of zombies, and it had good performance. It may be the way with how NPCS handle soundplaying as stated earlier, when off yielded even better results.

Alright, final edit for now. Here is the main bit that handles soundplaying for zombies.

self.DocileActionTypes = {
		[1] = function()
			self.StateChangeable = false
			self:ResetStills()
			local chance = math.random(1,5)
			local selectedAnim = self.CachedAnimations.Wanders[math.random(1,#self.CachedAnimations.Wanders)]
			self.Humanoid.WalkSpeed = math.random(1,5)
			selectedAnim:Play()
			selectedAnim:AdjustSpeed(self.Humanoid.WalkSpeed / 4)
			self.NextWander = tick() + math.huge
			local X = math.random(-100,100) 
			local Z = math.random(-100,100)
			local wanderPos = self.Root.Position + Vector3.new(X,0,Z)
			local ray = Utility("Raycast",self.Root.Position,wanderPos,{self.Model})
			if ray then
				wanderPos = (ray.Position + self.Root.Position) / 2
			end

			self.Humanoid:MoveTo(wanderPos)
			self:Look(wanderPos)
			self.Humanoid.MoveToFinished:Once(function()
				selectedAnim:Stop()
				self.Humanoid.WalkSpeed = self.WalkSpeed
				Utility("PlaySound",self.IdleSounds[math.random(1,#self.IdleSounds)].Name,NPCModel.Head,{PlaybackRegion = NumberRange.new(0,5)})
				self.NextWander = tick() + 5
				self.StateChangeable = true
			end)
		end,
		[2] = function()
			self.StateChangeable = false
			local chance = math.random(1,3)
			self.NextWander = tick() + math.huge
			self:ResetStills()

			local animation = self.CachedAnimations.Idle
			if chance == 1  then animation = self.CachedAnimations.Stills[math.random(1,#self.CachedAnimations.Stills)] end
			animation:Play()
			self.StateChangeable = true
			if animation.Animation.Name == "SitEnter" then
				self.SitConnection = animation.Stopped:Once(function()
					self.CachedAnimations.SitStay:Play()
					self.SitConnection = nil
				end)
			end
			local m = math.random(15,30)
			Utility("PlaySound",self.IdleSounds[math.random(1,#self.IdleSounds)].Name,NPCModel.Head,{PlaybackRegion = NumberRange.new(0,m)})
			self.NextWander = tick() + m
		end,
		[3] = function()
			self:ResetStills()
			self.StateChangeable = false
			local track = self.CachedAnimations.Looks[math.random(1,#self.CachedAnimations.Looks)]
			track:Play()
			track.Stopped:Once(function()
				self.StateChangeable = true
			end)
			self.NextWander = tick() + math.huge
			Utility("PlaySound","Aggro_1",self.Model.Head,{TimePosition = math.random(0,6)},nil,self.VoicePack)
			self.NextWander = tick() + math.random(4,8)
		end,
	}

What you’re showing here is your server stats, I was referring to the client’s network receive, from the performance stats bar in the clips that you’ve provided. Nevertheless, from what you’ve shown, the main values you should be concerned over is your average data ping, data throughput ratio, and average ISR packets/s.

From just increasing the number of zombies, the server is falling behind on network replication (average data ping), data being sent only increased by a small amount (total data KB/s), but the number of packets you’re sending greatly increased (average ISR packets/s), and most concerningly, your data throughput ratio shoots up by a significant amount. Normally, your data throughput ratio should remain at 1, with occasional spikes, but even with a lesser amount of zombies, it’s sitting at a hefty ratio of 23.

There is a lot of abnormal network congestion going on here, I highly doubt this is coming from just sending a few bits of data to play sounds on the client. How do your client and server stats look like if you just avoid trying to play sound at all? If they’re about the same, I would recommend looking into your zombie system as a whole as the primary issue.

I see. I’ll just have to look into it even further then. The data I send back and forth with remotes are handled by a client server and module script. The client and server goes through all the remotes and hooks them to an event binded to the module, that handles the remote events functions. At most, from what I’ve seen, the sound client event is what is causing this lag I feel like. But i don’t get why which is the problem. It’s just a request to a module script, which then fires a remote to the client, containing the parent, sound instance, and properties.

I’ve found a solution. The lag WAS coming from client soundplaying. The problem was that each zombie would create many idle sounds at a time, which caused a lot of replication issues hence the lag. I just ratelimited certain sounds from playing all the time, which fixed the issue.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.