the way the guy originally did it in that first post looks a little performance-heavy and complex. i mean, despite it being accurate, i feel like you can still cheat the way it’s done and do other easier.
let’s imagine a build like this:
you have three rooms, each of which is connected with their own doorways (which i will call “portals” because the post you linked kind of called it as such).
sound is playing from room 1, player is in room 3.
here’s two roughly thought out ways on the top of my head:
1) rooms and/or portals
this is based off the first post you sent (the one trying to be more accurate/complex), but a little more simpler to pull off.
because these rooms are each connected with a door inbetween them, i’m going to first order the rooms in a list like this:
-- room 1 -- portal 1 -- room 2 -- portal 2 -- room 3
-- ^ sound ^ player
i think you can kind of see where i’m going to go with this.
you can detect where the sound is and the player is between rooms however you want (either collisions, or checking the position every few frames or so, etc.).
the key point to take out of this is for every “room” or “portal” farther away the player is, the more muffled the sound will get.
i’m using both rooms and portals because you can be a room, but still be able to hear fine through the doorway/portal because nothing is blocking it from the other room–explained at the very end.
code-like, it could look something like this roughly (not to be used, just to show the process):
-- (local script because this can affect players differently based on their positions)
-- making a list for the sounds (or you can call for it from somewhere else):
local sounds = [Workspace.Sound1, Workspace.Sound2 ...]
-- making a dictionary for the rooms, and their muffling power:
local roomList = {
{order = 1, name = "room1", mufflePower = 0.3},
{order = 2, name = "portal1", mufflePower = 0.1} -- ....
}
RunService.Heartbeat:Connect(function() --(repeating however much you want ...)
-- some function to get where the player is
local CurrentLoc = GetPlayerRoomLocation(somePlayer)
for _, CurrentSound in ipairs(sounds) do -- loop through sounds
-- some function to get the sound's location
local CurrentSoundLoc = GetSoundRoomLocation(CurrentSound)
local mufflePower = 0
for i=CurrentLoc.order, CurrentSound.order, 1 do -- for each room inbetween ..
mufflePower += roomList[i].mufflePower -- add muffle power
end
-- do something to change the sound's muffle with the new mufflePower
end
)
this will work if you have rooms like the drawing above, were they constantly turn and move around, and aren’t in one straight hallway. the muffling is caused by sound trying to vibrate its way through hard surfaces (walls), resulting in the higher frequencies to be subdued, but obviously that’s not going to be realistic in a straight line of multiple rooms with no walls inbetween. so this one is really for more realistic mazy-turny areas, where you don’t want player to hear something through a wall even though the path to reach that point is very long (imagine very sound-proof walls).
if you do want that, though, i’d imagine the next kind would be easier to do:
2) wall collisions
sounds can both “bounce” off of things, which is good for #1, since the farther away the sound is, the harder it is for its vibrations to bounce to you, but it can also be “absorbed” by materials, some more than others.
if you’re less concerned by accuracy, and more just want it to be muffled behind ANY kind of wall (and not worry about long hallways, this one’s for you.
now, you don’t need a list of rooms, but you might want to get a good list of “walls” you want to be able to “collide” with the sounds. a simply stupid but easy way i thought of at the top of my head is just to label any “walls” you want with a specific collision group. you can just check it that way.
last time i checked on roblox docs, i didn’t find anything for segment/line collisions that grab more than one object (raycasting only shoots for one collision and is infinite in one direction), so the only other way i could think of is by using a long part (within the same collision group as your walls) connecting between you and the sound. you can then use the Part:GetTouchingParts
to get a list of colliding walls. idk if it’s good performance wise–someone else would have to put in a couple of cents for that–but it should technically work.
kind of like this:
local sounds = [Workspace.Sound1, Workspace.Sound2 ...]
-- colliding part
local CollisionPart = --[part here]
RunService.Heartbeat:Connect(function() --(repeating however much you want ...)
for _, CurrentSound in ipairs(sounds) do -- loop through sounds
-- get the part to transform right between u + sound
CollisionPart:SetCFrame( ... )
-- some function to get the sound's location
local Walls = CollisionPart:GetTouchingParts
local mufflePower = 0.1 * #Walls
-- perhaps add attributes to the walls if you want varying "muffle power?"
-- change sound's muffle to mufflePower
( ... )
end
)
if there’s anything segment-wise that can be used for collisions, then great, otherwise, this might be the best for that, LOL. i feel like there is some easier way to check for collisions. but you get the idea.
in the end, you can always:
3) use a bit of both, or go your own direction
for example, you can use the #1 way for muffling sounds through rooms, but also have the #2 way to check if there’s actually no walls inbetween you and the sound–only that you’re just very far away. y’know, what i was talking about with using the portals earlier.
and by all means, if you find a better way as you work through it, give it a shot! this kind of treads more into game design than scripting. not necessarily how to type it out, but how to concept setting it up.
sorry for the long reply, haha. but i hope it helps you understand!