How to make an interactive and engaging main menu!

So making a main menu isn’t as hard as you think! The hardest part might be making the main menu, making sure it fits on all devices. Takes time but it’s totally worth it.

Here is a menu I created for one of my games:

IF YOU WISH TO SKIP THE TUTORIAL, THERE IS A MODEL BELOW THAT IS ALREADY MADE! YOU CAN USE THAT!


Making the GUI

IMPORTANT
  • When sizing your frames, buttons and labels, YOU NEED TO SIZE THEM BY SCALE, NOT OFFSET! Sizing by the scale makes sure the UI will fit on all devices. Sizing by offset is not what you want.

When making the GUI, you must be mindful that it’s local. Settings, tweens and chat will all be local, so other players can’t see it.

  1. Insert a ScreenGui inside of StarterGui. Name it, “MainMenu”.
  2. Enable IgnoreGuiInset. This way, the menu will fit on the entire screen. If this is disabled, you will see a bar on the top of the screen which will cut the menu off. You don’t want this.
  3. Add a BoolValue inside of the ScreenGui and name it, “Closed”. This will be used later when scripting the menu!
  4. Ignore if you DON’T want a background in your menu. | Add a frame inside of the MainMenu and name it, “BackgroundFrame”. You can style it HOWEVER you’d like! Remember, this is the background, not the menu. Make the size of the background frame 1,0,1,0 (full size). I suggest having the background a tiny bit transparent (0.2) to help add a blur effect later.
  5. Add a frame and keep it called, “Frame”. This is where everything will be on. Make the size of the frame 1,0,1,0 and customize if however you’d like! I added a “DropStyle” style to mine!
  6. Start making the buttons. I made 2 image buttons and 2 text buttons. They both have the exact same scripts.
  7. Add a frame within the menu frame and name it, “Credits”. This is where you can add credits, or just general information that you want your players to know about before entering your game. Customize it however you’d like.
  8. Clone the “Credits” frame and name that frame, “SettingsFrame”. This will be the frame with all of the user settings. Add all of the settings within it then make its visibility false for now.
  9. Add a title and a subtitle if you wish. I added a gradient in my title to make it look more appealing!
  10. Add a TextButton inside of the ScreenGui and name it, “OpenMenu”. This is the button that will open the menu if it’s closed. Customize it and set its visibility to false.

You completed making your menu! Phew that was a lot! Let us start scripting it.


Scripting your Play Button

So let us start by scripting the play buttons! We’ll be using Robloxs’ TweenService for this! The BoolValue we created earlier will sure help us now!

Before we move on, go to Lighting and add a BlurEffect. Name it, “MenuBlue”.

Lets define our variables:

local TweenService = game:GetService("TweenService")
local player = game.Players.LocalPlayer -- The local player as we want this to be local
local frame1 = player.PlayerGui:WaitForChild("MainMenu").Frame
local frame2 = player.PlayerGui:WaitForChild("MainMenu").BackGroundFrame
local db = false -- Debounce/cooldown
local blur = game.Lighting.MenuBlur -- The blur we added before making this script

Awesome! Now, we can go ahead and add our code! I added a few notes in the code to help explain what each line means!

script.Parent.MouseButton1Click:Connect(function()
	if frame1.Parent.Closed.Value == false then -- This checks if the "closed" value is false. We want to make sure it's closed before trying to close it...again...
		if db == false then -- Checks if debounce is off
			db = true -- Sets it to true
			local goal = {}
			goal.Position = UDim2.new(1,0,0,0) -- This is where we want it to go. (Right side of the screen). You can change it to whatever position you'd like.

			local tweenInfo = TweenInfo.new(2, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out) -- Again, these are the tween settings, which you can change however you'd like.
			local tween1 = TweenService:Create(frame1, tweenInfo, goal) -- Making tween1
			local tween2 = TweenService:Create(frame2, tweenInfo, goal) -- Making tween2

			tween1:Play() -- Playing both tweens
			tween2:Play()

			if blur.Size == 24 then -- Here, we are changing the value of the blur effect. Once we close the menu, we want to remove the blur slowly. This adds a better effect to your menu.
				while wait(0.1) do -- Every 0.1 seconds, it removes 1 from the current value of 24 in the blur.
					blur.Size -= 1

					if blur.Size == 0 then -- Once it reaches 0, it breaks and continues.
						break
					end
				end
			end

			frame1.Parent.OpenMenu.Visible = true -- This enables the open menu button.
			wait(3) -- Cooldown time
			frame1.Position = UDim2.new(-1,0,0,0) -- This makes the frame go to the other side of the screen. Thats what you saw on my video. It adds a cooler effect to the menu.
			frame1.Visible = false -- Making sure the frame is not visible anymore :)
			frame2.Position = UDim2.new(-1,0,0,0)
			frame2.Visible = false
			frame1.Parent.Closed.Value = true -- Setting the close value to true
			db = false -- Turning off cooldown
			print("Closing menu complete") -- Printing success message!
		end
	end
end)

Awesome! We scripted the close button! Copy and paste this script to the ImageButton/TextButton so it works on both buttons.


Scripting your Settings

First, before scripting, make sure your settings are ready!

Once you have your settings ready, go ahead to the settings button that opens the settings frame.

This is the code you want to add:

local player = game.Players.LocalPlayer
local frame = player.PlayerGui:WaitForChild("MainMenu").Frame
local Credits = frame.Credits
local settingsFrame = frame.SettingsFrame

script.Parent.MouseButton1Click:Connect(function()
	if Credits.Visible == true then
		Credits.Visible = false
		settingsFrame.Visible = true
	else
		Credits.Visible = true
		settingsFrame.Visible = false
	end
end)

Clone this local script to any buttons that open the settings frame.

This only opens the settings frame and closes the credits frame. If you click the button again, it closes the settings frame and opens the credits frame. Its like a toggle button!

Now go ahead to your FOV (Field of View) setting and add the following code to the TEXTBOX:

local camera = workspace.CurrentCamera -- Access to the players camera
local fovText = game.Players.LocalPlayer.PlayerGui:WaitForChild("MainMenu").Frame.SettingsFrame.FOVText

fovText.FocusLost:Connect(function(enterPressed)
	if enterPressed then -- If the player pressed "enter" on their keyboard...
			camera.FieldOfView = fovText.Text
		end
	end
end)

Easy peasy. Next, go to the sound button and enter this script:

local sound = sound -- Enter where your sound is located. Because this is a local script, it will turn off the sound to the local player only.
local player = game.Players.LocalPlayer
local playing = true -- By default, the sound is playing

script.Parent.MouseButton1Click:Connect(function()
	if playing == true then -- If the sound is playing...
		sound.Playing = false
		player.PlayerGui:WaitForChild("MainMenu").Frame.SettingsFrame.SoundOnOrOff.Text = "Off"
	else -- If the sound isn't playing...
		sound.Playing = true
		player.PlayerGui:WaitForChild("MainMenu").Frame.SettingsFrame.SoundOnOrOff.Text = "On"
	end
end)

Done and done! Next one is probably the hardest setting to make… the chat theme…

Enter this local script inside of the Chat Theme button:

local player = game.Players.LocalPlayer
local white = true -- By default, the chat is white themed
local ChatTheme = player.PlayerGui:WaitForChild("MainMenu").Frame.SettingsFrame.ChatThemeButton
local chat = game:GetService("Chat")

script.Parent.MouseButton1Click:Connect(function()
	if white == true then
		white = false
		local settings = {		-- Now here, you can edit it to anything you want! These are the chat settings that are applied after the player clicks the button! Make sure the background color and the text color are different.

			BubbleDuration = 15,
			MaxBubbles = 3,

			BackgroundColor3 = Color3.fromRGB(0,0,0),
			TextColor3 = Color3.fromRGB(250,250,250),
			TextSize = 16,
			Font = Enum.Font.GothamSemibold,
			Transparency = .1,
			CornerRadius = UDim.new(0, 12),
			TailVisible = true,
			Padding = 8,
			MaxWidth = 300,

			VerticalStudsOffset = 0,

			BubblesSpacing = 6,

			MinimizeDistance = 40,
			MaxDistance = 100,
		}
		
		ChatTheme.Text = "Black" -- Sets the text in the theme button to "Black"
		
		pcall(function()
			game:GetService("Chat"):SetBubbleChatSettings(settings) -- Applies the settings
			print("Chat settings applied") -- Success message
		end)
	else
		white = true -- If the value was "Black" then...
		local settings = {		

			BubbleDuration = 15,
			MaxBubbles = 3,

			BackgroundColor3 = Color3.fromRGB(250,250,250),
			TextColor3 = Color3.fromRGB(0,0,0),
			TextSize = 16,
			Font = Enum.Font.GothamSemibold,
			Transparency = .1,
			CornerRadius = UDim.new(0, 12),
			TailVisible = true,
			Padding = 8,
			MaxWidth = 300,

			VerticalStudsOffset = 0,

			BubblesSpacing = 6,

			MinimizeDistance = 40,
			MaxDistance = 100,
		}
		
		pcall(function()
			game:GetService("Chat"):SetBubbleChatSettings(settings) -- Applies
			print("Chat settings applied") -- Success
		end)
		
		ChatTheme.Text = "White" -- Changes the theme button text to white.
	end
end)

And thats done!


Scripting the open button

Last thing we have to do is script the open button…

Lets define our variables first.

local player = game.Players.LocalPlayer
local frame1 = player.PlayerGui:WaitForChild("MainMenu").Frame
local frame2 = player.PlayerGui:WaitForChild("MainMenu").BackGroundFrame
local TweenService = game:GetService("TweenService")
local closed = frame1.Parent.Closed
local db = false
local blur = game.Lighting.MenuBlur

By now, you should see these and think that they are familiar… yes! They are! We used the same variables in our close button.

Rest of the script:

script.Parent.MouseButton1Click:Connect(function()
	if db == false then
		if closed.Value == true then -- If the closed value is true (meaning its closed), then...
			db = true
			local goal = {}
			goal.Position = UDim2.new(0,0,0,0) -- This is the centre of the screen. We want the menu to go there.

			local tweenInfo = TweenInfo.new(2, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out) -- Change if you wish...
			local tween1 = TweenService:Create(frame1, tweenInfo, goal)
			local tween2 = TweenService:Create(frame2, tweenInfo, goal)

			frame1.Visible = true -- Making sure our frames are visible before tweening
			frame2.Visible = true

			tween1:Play() -- Tween both frames.
			tween2:Play()

            frame1.Parent.OpenMenu.Visible = false -- Makes the open button disappear...

			if blur.Enabled == false then -- Making sure the blue effect is enabled...
				blur.Enabled = true
			end

			if blur.Size == 0 then -- Here, we are checking the blur is at 0, just to make sure our blur is disabled.
				while wait(0.1) do -- Every 0.1 seconds, it adds 1 to the size of the blur.
					blur.Size += 1

					if blur.Size ==  24 then -- Once it gets to 24, it stops and the script continues.
						break
					end
				end
			end
			wait(1)
			closed.Value = false -- Changes the closed value to false meaning its open
			db = false -- Cooldown is off!
		else
			warn("DB On")
		end
	end
end)

Thats all you have to do! You just finished making your very own interactive main menu with settings!


Conclusion

Below I have attached the model, if you want to just download it and add it! Once you insert it, just move the ScreenGui to StarterGui and move the MenuBlur to Lighting.

Feedback and/or suggestions on how to edit the script are much appreciated!

DevForum Main Menu Model

30 Likes

Updated the tutorial! Everything is correct! :smiley: Enjoy!

6 Likes

pretty cool. I was just thinking about making a menu for my game the other day lol. Keep up the great work

1 Like