I’m excited to share with you a new project I’ve been working on. I’ve created a game featuring a volumetric audio system that adds depth and immersion to your gameplay. You can check it out here: Game Link.
Feel free to explore and even copy the game if you want to experiment with it yourself. The magic happens in the StarterPack, where you’ll find the main script. It’s a small addition that can make a big difference in the overall atmosphere of your games.
I hope you enjoy playing around with it as much as I enjoyed creating it. Let me know your thoughts and any feedback you might have!
If your game has many sounds, then this version of the script might not be best for optimization. I plan to make a new, improved and optimized version of this volumetric audio system. Stabilizing optimization and realism is my goal in the new version.
If your game is realistic and you want a realistic sound experience then this is the simplest way. In this version of the script, it only checks to see if you’re behind a wall and muffles the sound, and adjusts the sound volume based on how far you are from the sound source.
In the next version though, it will have material “sound wave” absorption so let’s say the part that’s blocking the sound source is fabric, then it will only add a small muffle, but if it’s something like metal then it would be muffled.
As well as in the next version, I’m adding raycast bounce reflections, so it will add reverb based on how many parts each ray hits.
I thought that using the camera would be more appropriate, although if it really should be where the players head/body is then I can change it to that. I have no problem changing it since both ways makes sense to me (camera vs player head).
23:40:21.185 Lord_BradyRocks's Place Number: 1001 auto-recovery file was created - Studio
23:40:23.737 [ACTION ITEM] Experience doesn't have permissions for sound asset 16491133121. Click here to grant experience permission to asset. - Studio
23:40:23.737 Failed to load sound rbxassetid://16491133121: User is not authorized to access Asset. (x5) - Studio
23:40:24.099 [ACTION ITEM] Experience doesn't have permissions for sound asset 16491133121. Click here to grant experience permission to asset. - Studio
23:40:24.099 Failed to load sound rbxassetid://16491133121: User is not authorized to access Asset. (x5) - Studio
The sound was uploaded to my profile so that’s why you can’t hear it, you can replace it with a Roblox free sound if you want, I will instead upload it to the game assets but I don’t think this will actually solve the issue.
First off, I love this! I’ve needed something like this for so long and it works perfectly. I’m mainly replying however because I’ve actually taken your original script and modified it to be a bunch more optimized for games with larger workspaces.
No longer orients through workspace every heartbeat
All sounds in the workspace before the game begins must be tagged with “TrackSound”
Any instances added or removed from the workspace fire a set of functions that will check and see if it is a sound needed to be added to the ray casts of the volumetric audio
-- by Rylen
-- 2/23/24 @ 10:46 PM
local RunService = game:GetService("RunService");
local Players = game:GetService("Players");
local Player = Players.LocalPlayer;
local Camera = workspace.CurrentCamera;
local CollectionService = game:GetService("CollectionService");
local Sounds = {};
local Params = RaycastParams.new();
Params.BruteForceAllSlow = false;
Params.IgnoreWater = true;
Params.RespectCanCollide = false;
Params.FilterType = Enum.RaycastFilterType.Exclude;
function Lerp(Start, Goal, Alpha)
return Start + (Goal - Start) * Alpha;
end;
local function InitializeSound(Object)
Sounds[Object] = {
["MaxVolume"] = Object.Volume,
["MaxAudibleDistance"] = Object:GetAttribute("MaxAudibleDistance") or 50,
};
local EqualizerSoundEffect = Instance.new("EqualizerSoundEffect", Object);
EqualizerSoundEffect.Name = "Equalizer";
EqualizerSoundEffect.Enabled = true;
EqualizerSoundEffect.HighGain = 0;
EqualizerSoundEffect.MidGain = 0;
EqualizerSoundEffect.LowGain = 0;
EqualizerSoundEffect.Parent = Object;
end;
-- Detect whether a sound is being added or removed from the workspace (Fired with connections below) --
local function OnSoundAdded(Object)
if Object:IsA("Sound") and Object.Parent:IsA("BasePart") then
if not Sounds[Object] then
InitializeSound(Object);
end
end
end
local function OnSoundRemoved(Object)
if Sounds[Object] then
Sounds[Object] = nil;
end
end
-- Fire above functions whenever something is added to the workspace --
workspace.DescendantAdded:Connect(OnSoundAdded);
workspace.DescendantRemoving:Connect(OnSoundRemoved);
-- SET UP PRE-EXISTING SOUNDS --
for _, Object in pairs(CollectionService:GetTagged("TrackSound")) do
OnSoundAdded(Object)
end
RunService.Heartbeat:Connect(function()
for Sound, Properties in pairs(Sounds) do
local Part = Sound.Parent;
local MaxVolume = Properties.MaxVolume;
local Distance = (Camera.CFrame.Position - Part.Position).Magnitude;
if Distance < Properties.MaxAudibleDistance then
Params.FilterDescendantsInstances = (function()
local Results = {Part};
for _, User in pairs(Players:GetPlayers()) do
if User.Character then
for _, Object in pairs(User.Character:GetDescendants()) do
if Object:IsA("BasePart") then
table.insert(Results, Object);
end
end
end
end
return Results;
end)();
local RaycastResults = workspace:Raycast(Camera.CFrame.Position, Part.Position - Camera.CFrame.Position, Params);
if RaycastResults then
local MuffleFactor = 1 - (1 - math.min(Distance / Properties.MaxAudibleDistance, 1));
Sound.Equalizer.HighGain = Lerp(Sound.Equalizer.HighGain, -80 * MuffleFactor, 0.25);
Sound.Equalizer.MidGain = Lerp(Sound.Equalizer.MidGain, -80 * MuffleFactor, 0.25);
Sound.Equalizer.LowGain = Lerp(Sound.Equalizer.LowGain, -20 * MuffleFactor, 0.25);
else
Sound.Equalizer.HighGain = Lerp(Sound.Equalizer.HighGain, 0, 0.15);
Sound.Equalizer.MidGain = Lerp(Sound.Equalizer.MidGain, 0, 0.15);
Sound.Equalizer.LowGain = Lerp(Sound.Equalizer.LowGain, 0, 0.15);
end
Sound.Volume = MaxVolume * (1 - (Distance / Properties.MaxAudibleDistance));
end
end;
end);
Again, thank you for making this, and I hope this helps anyone who may want to use this in games with a large workspace!
Hey! This system is great! I do have a few suggestions from looking at the source code and some adjustments from another similar system called “3d sound system”
Link: 3D Sound System - Realistic frequency dampening
Add sound dampening like 3d sound system to enhance immersion.
(Fork it from them lol)
Control sound volume(volumetric) behind a wall by firing a ray cast though the wall to detect how far away it is and / it by thickness of the wall to produce the perfect volumetric calculation.
These suggestions are just stuff I would be glad to see!
Not much since the video, I’ve just started school and I’m thinking exactly how this will work.
A clone of the main sound source will be parented to a pair of attachments which are: 5 closest to the player, and 5 farthest from the player (editable). The sounds will have reverb and the other sound effects that roblox offers. Using this will allow the sound bounces which I wanna add. If you have questions I’m sure I have an answer. If you’re a developer maybe we could work on this together.