Hello, I am making a horror game that is inspired by the backrooms and I am trying to create a system that “dynamically” changes audio to be louder or quieter depending on if the player is near or far from any light sources. I am wondering if it’s possible to create an effect, and if so, how could I achieve this?
The game consists of A TON of light sources and A TON of dark areas, and I don’t find it pleasing to have light humming play when there are no lights in sight.
If you need any clarification or have questions, please feel free to reply!
I don’t believe Raycasting is the best solution here. It would work with enough effort but I think the first reply is a far better and cleaner solution if you want to handle this programmatically.
There is a better solution though! Sounds have a distance property as long as the sound is parented within a BasePart. You can easily preview how the sound will sound like by following these steps:
Insert a Sound object into a BasePart
Set the Looped property to true
Set the Playing property to true
Select your BasePart
Pan your camera around!
Then play around with the properties under the “Emitter” tab in the sound object and tune it to your preference!
If you insist on doing this through code a magnitude check should be sufficient to provide you with an accurate distance
local MainPart = --The primary part, like your characters HumanoidRootPart
local SourcePart = --The source part, like another player or a stationary part
local Distance = (SourcePart.Position - MainPart.Position).Magnitude
print(Distance) --The distance is represented in studs, use this number to fine tune your sound volume.```
Yes, putting sounds in 1k light sources would probably be the easiest solution, not sure how optimized it would be to iterate through 1k objects just to control distance though so letting the properties handle that would be ideal. I’ve never worked with thousands of sounds in a game before so I’m not sure how viable it is to do that, so if anyone else knows more about how to handle sounds then it would be nice if you could share your insight here!
I was just thinking if the player is near a light, the sound plays. If not, the volume is lowered. Not nothing crazy like reparenting and Instance cloning, etc. Just one sound that changes volume
I’m pretty sure what he was saying is that what you are asking for already comes with the light object, just change the properties to what @OKevinO listed above
if you are kinda lazy, just loop through all of workspace, and its not worth the fps
local RunService = game:GetService("RunService")
local Character = script.Parent -- starter character scripts bnn
local Sound = script:WaitForChild("Sound", math.huge)
local MaxVolume = 2
RunService.RenderStepped:Connect(function()
local Volume = 0
local CharacterPos = Character:GetPivot().Position
for i, Object : Instance in pairs(workspace:GetDescendants()) do
local ObjectVolume = 0
if Object:IsA("Light") and Object.Parent:IsA("BasePart") then
local Range = Object.Range
local Brightness = Object.Brightness
local Distance = (Object.Parent.Position - CharacterPos).Magnitude
if Distance <= Range then
ObjectVolume = MaxVolume + (0 - MaxVolume) * (Distance / Range)
end
end
if ObjectVolume > Volume then
Volume = ObjectVolume
end
end
print(Volume)
Sound.Volume = Volume
end)
Looping through 1k objects per frame is pretty much fine, but if you increase the light source or change the code to make more calculations, it gets super performance heavy and might ruin players’ experiences.
A workaround might be using regions to detect lights nearby, then loop through them.
local overlapParams = OverlapsParams.new()
overlapParams.FilterDescendantInstances = {workspace.Lights}
overlapParams.FilterType = Enum.RaycastFilterType.Whitelist
local lights = workspace:GetPartBoundsInRadius(humanoidRootPart.Position, RANGE, overlapParams)
for _, light in ipairs(lights) do
-- you can now check the nearest light by looping through them now
end
You can use this in unison with the magnitude method to better manage how many sounds are playing in a given workspace for the client. Setting a maximum distance threshold from any light source stops playing those that are outside the threshold.
It’s the same logic to choose the nearest light but less performance heavy because it loops through fewer lights since I only made it loop through the lights “near” them.
I’d suggest trying and testing both ways as suggested above.
*just put the sound in every light and set the maxrolloffdistance to whatever you want as the distsnce you want a player to be from the light to hear the sound.
*use the magnitude script mentioned.
Play the game both ways to see which has the best performance. I have a place wuth many sounds in it set up using min & maxrolloff and it works well, but I’ve never tried using thousands of sounds.
Maybe try something with streamingenabled to see if it helps.
I’ve tried streamingenabled and it caused random lag on studio. I’m getting 60fps without an fps unlocker and honestly, it’s quite smooth for the number of lights there are.