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.
I’m using a chunk system for the attachments which can be edited; in the video I show this. I added this so that attachments arn’t so close together and for “performance” to control the amount of attachments.
Essentially, Its a a imaginary Vector3 based shape that has functions like “GetPartsInPart”
Its a solution to hitbox or detection methods that use parts (which costs performance). Instead you can just check without instancing anything new.
Hitbox Module Using Spatial Query: Hitbox.rbxm (8.8 KB)
In most cases, Yes. Vastly. This is because of cuts on memory usage, Math, Creation and deletion, and the new method which actually has decent code (Compared to old functions)
Imagine a box, Lets say i divide this box into sections called “Chunks”. Each chunk is its own independent existence and has its own calculation.
You can split up the box into cubes or spheres. Whatever suits your needs but the idea is that using vectormapping you can split up the cost of operation a ton. By essentially getting rid of something called “Junk Calculation”
“Junk Calculation” is when roblox was about to calculate something that didnt need to be and it has to clean it up. This happens the bigger or more “Heavy” something is.
the functionality seems to be working just fine despite the error.
it only happens in my game, not in your demo place.
if you have any ideas about why this might be happening or how to resolve it, I’d really appreciate your insight.
but again, the system is fantastic, and I’m really enjoying using it.
I’d recommend using the optimized version. But your error is caused by your sound’s parent not being a basepart. You can add an if statement to check if it is a basepart and skip it to remove this issue.