local songs = script.Parent
while wait() do
for i, song in pairs(songs:GetChildren()) do
if song:IsA("Sound") then
local randomNo = math.random(1, #songs:GetChildren())
local randomSong = songs:GetChildren()[randomNo]
local randomSongMuffled = songs:FindFirstChild(randomSong.Name.."Reverb")
randomSong:Play()
randomSongMuffled:Play()
randomSong.Ended:Wait()
randomSongMuffled.Ended:Wait()
end
end
end
Hi all, this is a script I have in which I want “randomSong” and “randomSongMuffled” to be played at the same time, however this doesn’t seem to work properly, only “randomSongMuffled” plays and “randomSong” does not. I don’t really script so I would appreciate if someone could help me with this.
I can’t exactly tell, but it seems like the culprit here is poor structuring of data. You’re mixing muffled tracks with normal tracks and mixing Sounds and other Instance types into one place. This can cause you to play a muffled track twice, or cause an error as your code might try to run Play on a Script.
First, I’d suggest making each normal Sound (not the Reverb types) a child of the script. This makes sorting it easier as you’ll ensure every child of the script is a Sound, and you won’t have a script mixed in with them.
Next, make each “Reverb” sound a child of the normal sound. Instead of having the normal and Reverb versions all in one place, simply have a hierarchy like script.SoundName.Reverb where Reverb is the “muffled” version of the song.
Now, since you know every child of script is a sound and that every child of script should have a child named Reverb (or whatever you want), you have a much more straightforward solution.
while true do -- Don't do wait/task.wait here... just don't v_v
local songs = script:GetChildren() -- We can store this as a variable for efficiency
local randomNo = math.random(1, #songs)
local randomSong = songs[randomNo]
local randomSongMuffled = randomSong.Reverb -- If you're not sure that `Reverb` will exist, use FindFirstChild and nil check it
randomSong:Play()
randomSongMuffled:Play()
randomSong.Ended:Wait()
randomSongMuffled:Stop() -- You could cause an infinite wait here if randomSongMuffled is already ended.
-- I choose to just stop it outright, but you could check if you really want to:
-- if randomSongMuffled.IsPlaying then randomSongMuffled.Ended:Wait() end
-- I don't think this is necessary, though.
-- An explicit wait is not necessary here. `randomSong.Ended:Wait()` already does this for us.
end
Finally, make sure none of your Sound instances have Looped set to true, or that will cause obvious problems.
--a function for fetching all current songs
local function getSongs(): {Sound}
local songs = {}
for _, v in pairs(script.Parent:GetChildren()) do
if v:IsA("Sound") then table.insert(songs, v) end
end
return songs
end
--a function that fetches the muffled song given the normal one
--I added the error because I suspect you used ChatGPT and "Reverb" was a hallucination
local function getMuffledSong(songs: {Sound}, songName: string): Sound
local song = script.Parent:FindFirstChild(songName.."Reverb")
if not song then
error(songName.." with reverb doesn't exist, create it!")
end
return song
end
--a function that combines both signals into one through a proxy event
--this assumes that both songs will end at some point (no pauses etc)
local function waitForSongsToFinish(song1: Sound, song2: Sound): ()
local proxy = Instance.new("BindableEvent")
local finished1 = false
local finished2 = false
song1.Ended:Once(function()
finished1 = true
if finished2 then proxy:Fire() end
end)
song2.Ended:Once(function()
finished2 = true
if finished1 then proxy:Fire() end
end)
proxy.Event:Wait()
proxy:Destroy()
end
while true do
--dynamically fetch songs on each iteration
local songs = getSongs()
--pick a song fully randomly
local song = songs[math.random(1, #songs)]
--from the song name, get the muffled song
local muffledSong = getMuffledSong(song.Name)
--play both songs
song:Play()
muffledSong:Play()
--wait for both songs to finish
waitForSongsToFinish(song, muffledSong)
end