How to script a music system with a mute option [OPEN-SOURCE GAME FILE INCLUDED]

Before we start, this can be quite tricky! I have created a open-source game so you can take this system without having to script it yourself. This is not advised, as this will also teach you on how to use this system and edit it to your liking.

Now lets gets scripting!

Step 1 - Scripting Music

The biggest part is actually making the song play!

Do not name the script Music! It can get confused with the actual music object and the script, resulting in errors.

Firstly, create a script inside of the workspace. Name it MusicScript.
image

Then, go into the script editor. We will have to write some code for it to work!

The code below is responsible for creating the music object. This is one of the most mandatory parts of the script!

local sound = Instance.new("Sound", workspace)
sound.Name = "Music"
sound.Playing = true
sound.Volume = 1

Now, we’ll script the event. This will trigger every time a song plays!

local musicEvent = Instance.new("RemoteEvent", game.ReplicatedStorage)
musicEvent.Name = "MusicEvent1"

local mp = game:GetService('MarketplaceService')

local music = {}
local requests = {}

function PositiveIntegerMask(String)
    return String:gsub("%D+", "")
end

for i,v in pairs(script.Sound:GetChildren()) do
	table.insert(music, v.SoundId)
end

local function IsSound(id)
	local success, value = pcall(function()
		return mp:GetProductInfo(id).AssetTypeId
	end)
	if success then
		if mp:GetProductInfo(id).AssetTypeId == 3 then
			return true
		else
			return false
		end
	else 
		return false
	end
end

Now we’ll be scripting what happens when the event occurs.

wait(.5)

function playMusica(SoundId)
	if #requests > 0 then
		local oldSong = sound.SoundId
		sound.SoundId = requests[1]
		sound.Playing = true
		local ID = PositiveIntegerMask(requests[1])
		local Asset = mp:GetProductInfo(ID)
		local Publisher = Asset.Creator.Name
		local AudioName = Asset.Name
		wait()
		requests['rbxassetid://'..ID] = nil
		table.remove(requests, 1)
		musicEvent:FireAllClients(Publisher, AudioName)
		sound:Play()
		return
	end
	local oldSong = sound.SoundId
	sound.SoundId = SoundId
	local ID = PositiveIntegerMask(SoundId)
	local Asset = mp:GetProductInfo(ID)
	local Publisher = Asset.Creator.Name
	local AudioName = Asset.Name
	wait(1)
	musicEvent:FireAllClients(Publisher, AudioName)
	sound:Play()
	sound.Playing = true
end

Now that the event scripting is done, we can move on to when a song changes. use the following code. (The print line of code is optional, mainly used for debugging)

wait(3)
print(#music)
playMusica(music[math.random(1, #music)])

sound.Ended:Connect(function()
	wait(0.5)
	local old = sound.SoundId
	local newSong = music[math.random(1, #music)]
	while(old == newSong) do
		newSong = music[math.random(1, #music)]
	end
	playMusica(newSong)
end)

Now, let’s script the final part of the music script - the skipping system. yes - this system comes with a skip option!

game.Players.PlayerAdded:Connect(function(p)
	p.Chatted:Connect(function(m)
		if(m:lower() == "!skip" or m:lower() == "/e !skip") then
			if p:GetRankInGroup(GROUPID) >= 10 then
				wait(0.1)
				local old = sound.SoundId
				local newSong = music[math.random(1, #music)]
				while(old == newSong) do
					newSong = music[math.random(1, #music)]
				end
				playMusica(newSong)
			end
		end
	end)
end)

Replace GROUPID with the ID of your group, and replace 10 with the minimum role ID needed to perform the skip.

You can also replace the command needed to skip. E.g., replace "!skip" with ":skipsong".

After that, you’ve finished the script. But you need some more things to make it work!

You’ll need to create a StringValue object named NowPlaying so it can get the name of the song. Keep it in workspace, it does not need to go inside of any scripts.

Now, make a folder inside of the MusicScript named Sound. In there, you can add as many sound objects as you like. The system will randomly pick one to play!

Feel free to change the name value of the song in properties, it won’t break the script.

Finally, just incase, I’ve attached below the full script what you should have written. Feel free to copy and paste.

Once you have made all the objects and put them in the right place, the workspace should look something like this:
image

Finished Script


local sound = Instance.new("Sound", workspace)
sound.Name = "Music"
sound.Playing = true
sound.Volume = 1


local musicEvent = Instance.new("RemoteEvent", game.ReplicatedStorage)
musicEvent.Name = "MusicEvent1"

local mp = game:GetService('MarketplaceService')

local music = {}
local requests = {}

function PositiveIntegerMask(String)
    return String:gsub("%D+", "")
end

for i,v in pairs(script.Sound:GetChildren()) do
	table.insert(music, v.SoundId)
end

local function IsSound(id)
	local success, value = pcall(function()
		return mp:GetProductInfo(id).AssetTypeId
	end)
	if success then
		if mp:GetProductInfo(id).AssetTypeId == 3 then
			return true
		else
			return false
		end
	else 
		return false
	end
end


wait(.5)

function playMusica(SoundId)
	if #requests > 0 then
		local oldSong = sound.SoundId
		sound.SoundId = requests[1]
		sound.Playing = true
		local ID = PositiveIntegerMask(requests[1])
		local Asset = mp:GetProductInfo(ID)
		local Publisher = Asset.Creator.Name
		local AudioName = Asset.Name
		wait()
		requests['rbxassetid://'..ID] = nil
		table.remove(requests, 1)
		musicEvent:FireAllClients(Publisher, AudioName)
		sound:Play()
		return
	end
	local oldSong = sound.SoundId
	sound.SoundId = SoundId
	local ID = PositiveIntegerMask(SoundId)
	local Asset = mp:GetProductInfo(ID)
	local Publisher = Asset.Creator.Name
	local AudioName = Asset.Name
	wait(1)
	musicEvent:FireAllClients(Publisher, AudioName)
	sound:Play()
	sound.Playing = true
end

wait(3)
print(#music)
playMusica(music[math.random(1, #music)])

sound.Ended:Connect(function()
	wait(0.5)
	local old = sound.SoundId
	local newSong = music[math.random(1, #music)]
	while(old == newSong) do
		newSong = music[math.random(1, #music)]
	end
	playMusica(newSong)
end)

game.Players.PlayerAdded:Connect(function(p)
	p.Chatted:Connect(function(m)
		if(m:lower() == "!skip" or m:lower() == "/e !skip") then
			if p:GetRankInGroup(4132824) >= 12 then
				wait(0.1)
				local old = sound.SoundId
				local newSong = music[math.random(1, #music)]
				while(old == newSong) do
					newSong = music[math.random(1, #music)]
				end
				playMusica(newSong)
			end
		end
	end)
end)```
Step 2 - Scripting Muting

Now we will move on to Step 2 - Notifications.

This is a big part of the project, as well! It lets you mute music. If you decide not to include this, your music will still play but you can not mute at all - players some times like to mute music.
Let’s start with creating a ScreenGui, named Mute. Place it in StarterGui.
image

Now create a TextButton! You can customize this however you like. This will be our mute button.

TIP: I recommend using Roblox’s new UICorners! They’re easy to use, and can roundify your UIs resulting in a more appealing look. This is what my Mute button looks like:
image

Now, we’ll script the muting. Add a Script inside of the TextButton.

local muted = false

script.Parent.MouseButton1Click:Connect(function()
	if muted == false then
		muted = true
		script.Parent.Text = "Unmute Music"
		game.Workspace.Music.Volume = 0.4
			wait(0.1)
		game.Workspace.Music.Volume = 0.3
			wait(0.1)
		game.Workspace.Music.Volume = 0.2
			wait(0.1)
		game.Workspace.Music.Volume = 0.1
			wait(0.1)
		game.Workspace.Music.Volume = 0
		
	else
		muted = false
		script.Parent.Text = "Mute Music"
		game.Workspace.Music.Volume = 0.1
		wait(0.1)
		game.Workspace.Music.Volume = 0.2
			wait(0.1)
		game.Workspace.Music.Volume = 0.3
			wait(0.1)
		game.Workspace.Music.Volume = 0.4
			wait(0.1)
		game.Workspace.Music.Volume = 0.5
		
		end
end)

This script will make the song volume fade in/out when you mute or unmute, and will also change the text of it. If you change the name of the music object replace Music in all of these code lines with the name of the object. (e.g. game.Workspace.myawesomemusic.Volume = 0.2)

Now we can code the color changing when you hover over the button. This is optional, but it can really transform the look of the UI! This is made by using TweenService. Credits to @Inkthirsty for teaching me about this!

local TS = game:GetService("TweenService")
local Goal1 = {} Goal1.BackgroundColor3 = Color3.fromRGB(197, 124, 126) 
local Goal2 = {} Goal2.BackgroundColor3 = Color3.fromRGB(232, 146, 147) 
local Tween1 = TS:Create(script.Parent, TweenInfo.new(0.5), Goal1)
local Tween2 = TS:Create(script.Parent, TweenInfo.new(0.5), Goal2)

script.Parent.MouseEnter:Connect(function()
    Tween1:Play()
end)

script.Parent.MouseLeave:Connect(function()
    Tween2:Play()
end)

You can change the RGB values with anything of your liking.
Goal2 is the colour when you are not hovering, and Goal1 is the colour when you are.
That’s it for the mute button! Click play and test it out.

Step 3 - Adding Events

Adding events is probably the most easy part of the system! Head to ReplicatedStorage and make two RemoteEvents inside of there. Name one of them MusicLog and one of them addSong. Make sure they are identical to what I have just wrote, so the script works!

A finished replicated storage should look something like this:
image

Once you have completed all 3 steps, you are finished! Please make sure to test your game out to see if it works. Feel free to give suggestions/feedback in the comments below, and like this if you believe this has helped you!

With that being said, have a nice day. Good luck with your game(s)!

54 Likes

The script worked as expected, however, changing the value of the song in properties (For example: Playback speed) does not apply afterwards when the game is being run.

2 Likes

Would anyone be interested in a V2, featuring a music menu where people can play their own songs for robux, music announcements etc?

2 Likes

Yes I would definitely be interested in this.

1 Like

Are you living under a rock? In all seriousness, you can’t with the new Roblox Audio Update.

1 Like

I like the script, but I was wondering if you want to keep it to 1 song only and keep it on loop how’d you make that work?

1 Like

You can if you find usable audio, such as the Monstercat collection.

2 Likes

You can either use Monstercat music, and possibly wait for people to upload new audio when it becomes available to do so.

1 Like

Hi everyone! Due to community demand, I’ve made a Version 2 featuring many more features like a full gui with a DevProduct request feature, commands and more.
Prism | Version 2 Music System