How to get sound effects to work on multiple sounds

I have multiple sounds playing at once (background music + sea ambience) when a player is near water. However, when they enter the water I want to create an underwater muffle (Underwater Muffle (Inspired by Polyhex)) but I want to keep it efficient, and I don’t wanna put an Equalizer and PitchShift inside every single sound. So I tried this


but effects need to be parented to the sound. So even when they are enabled, nothing happens.

How can I effectively do this, without having to have a dozen of these effects pasted into every single sound in the game? I want the effects to automatically apply to all sounds

3 Likes

To answer your question, if you put the effects and the sounds in the same sound group, you should be able to enable/disable them and have them effect everything.

2 Likes

Note this has been tested with at-least 4 songs, and is working.

1 Like

What @SorxtaKanda said. If that is still not what you want, you could apply this small code so that every sound has the those effects without having to manually do it yourself.

local soundFolder = game.SoundService.Effects.Underwater

local sounds = workspace.Sounds --- Or wherever your sounds are located.

for c, child in pairs(sounds:GetDescendants() do
    if child.className == "Sound" then
        local equalizer = soundFolder.Equalizer:Clone()
        local shift = soundFolder.PitchShift:Clone()

        equalizer.Parent = child
        shift.Parent = child
    end
end

Can I have sound grups inside of each other then?

> SoundGroup
    > Music (SoundGroup)
        > Music1
        > Music2
    > Sounds (SoundGroup)
        > Ocean

    > Equalizer
    > PitchShift

The sound doesn’t have to be in the soundgroup, it has a SoundGroup property; just assign it to the soundgroup that has the muffle effects

1 Like

Also note nesting sound groups does not apply the sound effect correspondingly

I need to sound to be in its own sound group tho, as I have settings to enable/disable sounds, music, etc. and I just wanna change the volume of the sound group

This solution might not give you the 1 to many relationship that you wanted, how ever sound effects per sound group would still solve a lot of the over using of instances.

1 Like

also it’d be relatively simple to make a script to toggle specific sound effects, if they were named similar.

for instance

local function toggleWaterEffects(bool)
    for i,v in pairs(game:GetService("SoundService"):GetDescendants()) do
        if v.Name:lower():find("watereffect") then
            v.Enabled = bool
        end
    end
end
2 Likes

I need a way to also lower the volume of the sounds tho, and have the sound in seperate groups :confused:

You can set the volume via sound groups tho, so unless you need them alone then I’m sure you could find a way to implement SoundGroup.Volume = .2 or whatever you may need.

Well the reason why I had 2 sound groups was because volume needs to be changeable for music, sfx, ambience, etc. are all seperate. So if the player wanted to mute music, but keep the ambience, or sfx, they would stay. So I cant have all the sounds under 1 sound grup

That’s not what I’m referring to, if you have them set to different sound groups you can set all the sound group volumes individually, and just toggle the sound effects per sound group.

the script I sent would allow you to toggle each effect, with just a function call for a structure like.

So I’d still need two of the effects?

Depending on which sound groups you want to effect, you’d need to place the effects in those sound groups.

local SoundService = game:GetService('SoundService')

local Music = SoundService:WaitForChild('Music')
local Sounds = SoundService:WaitForChild('Sounds')

local Camera = workspace.CurrentCamera

local Offset = 0.01

spawn(function()
	-- Check if player is in water
	while wait() do
		local Position = Camera.CFrame.Position
		
		local Min = Vector3.new(Position.X + Offset, Position.Y + Offset, Position.Z + Offset)
		local Max = Vector3.new(Position.X - Offset, Position.Y - Offset, Position.Z - Offset)
		
		local Region = Region3.new(Max, Min)
		Region = Region:ExpandToGrid(4)
		if Region then
			local Material = workspace.Terrain:ReadVoxels(Region, 4)
			if Material[1][1][1] == Enum.Material.Water then
				for i, v in pairs(SoundService:GetDescendants()) do
					if v:IsA('EqualizerSoundEffect') or v:IsA('PitchShiftSoundEffect') then
						v.Enalbed = true
					end
				end
			else
				for i, v in pairs(SoundService:GetDescendants()) do
					if v:IsA('EqualizerSoundEffect') or v:IsA('PitchShiftSoundEffect') then
						v.Enalbed = false
					end
				end
			end
		end
	end
end)

Enabled* however that looks like it should work, yes. However you can shorten it if you really wanted to.

for i, v in pairs(SoundService:GetDescendants()) do 
    if v:IsA('EqualizerSoundEffect') or v:IsA('PitchShiftSoundEffect') then
        v.Enabled = Material[1][1][1] == Enum.Material.Water
    end
end

this would just get rid of the need for the if else statement

4 Likes