A radial menu is a format of menu often found in console games because of its lull of use through analog thumbstick controllers. In a radial menu, the selectable alternatives are i ordered it in a ring. Once the user pushes the analog stick, the choice in the direction the user moved will be selected.

You are watching: How to make a start menu in roblox

This tutorial will certainly cover how to carry out a radial menu, with an emphasis on gamepads, back the same technique can be provided for mouse/keyboard or mobile games.

Setting up Menu

Menus have the right to be developed manually or through code. This tutorial offers code so that can easily be put into any type of game:


Building a Radial MenuExpected OutputExpand

-- define position and size for the menu framework in both opened and also closed stateslocal menuOpenPosition = UDim2.new(0.25, 0, 0.25, 0)local menuOpenSize = UDim2.new(0.5, 0, 0.5, 0)local menuClosedPosition = UDim2.new(.5, 0, .5, 0)local menuClosedSize = UDim2.new(0.005, 0, 0.005, 0)-- define the element for the food selection optionslocal itemTemplate = Instance.new("TextButton")itemTemplate.Size = UDim2.new(0.3, 0, 0.2, 0)itemTemplate.AutoButtonColor = falseitemTemplate.TextScaled = true-- develop a screen and also frame for the menulocal menuScreen = Instance.new("ScreenGui", player:WaitForChild("PlayerGui"))menuScreen.Name = "MenuScreen"local menuFrame = Instance.new("Frame", menuScreen)menuFrame.Size = menuClosedSizemenuFrame.Position = menuClosedPositionmenuFrame.Visible = falsemenuFrame.BackgroundTransparency = 1menuFrame.BorderSizePixel = 0menuFrame.Name = "MenuFrame"
Copy CodeLight Theme
Radial menus commonly have 2 states: opened and closed. This code an initial defines positions and also sizes because that the main frame of the menu. With the existing values, the open up state of the food selection will be focused on the screen and also take up fifty percent of the screen’s width and also height. Friend can readjust menuOpenPosition and menuOpenSize to change how lot of the display screen the menu takes up and also where the is centered.

Next, the manuscript creates a theme for the menu items. In this case, a TextButton is used, as it is simple. Girlfriend should adjust this to usage a more complex element the fits the layout of her game and interface. Save in mind the code will animate the menu opening by changing its size, for this reason TextButton/TextScaled makes sure the text dynamically changes size with the button.


AutoButtonColor is disabled together this indict is focused on working with a gamepad. If adapting this password for use v a mouse, girlfriend should allow this property.

Finally, the code creates a ScreenGui and also Frame. The Frame’s GuiObject/Size and GuiObject/Position are set to menuClosedSize and menuClosedPosition respectively, as the menu should be surprise initially.

Creating Buttons

After the menu screen and also frame are collection up, the manuscript then automatically creates buttons i ordered it in a ring. Over there are numerous constants you deserve to use come configure how plenty of buttons appear in the ring and also how they room oriented.


Creating a Radial menu ItemExpected OutputExpand

local RADIUS = .5local NUM_OPTIONS = 6local ANGLE_OFFSET = 90local menuItems = local role newMenuItem(name, angle, range)local newItem = local brand = itemTemplate:Clone()label.Text = namelabel.Name = namelocal angleRadians = math.rad(ANGLE_OFFSET + angle)label.Position = UDim2.new(.5 + RADIUS * math.cos(angleRadians) - label.Size.X.Scale / 2, 0, .5 - RADIUS * math.sin(angleRadians) - label.Size.Y.Scale / 2, 0)label.Parent = menuFramenewItem.Label = labelnewItem.Vector = Vector2.new(math.cos(angleRadians), math.sin(angleRadians))newItem.Range = rangetable.insert(menuItems, newItem)end
Copy CodeLight Theme
The newMenuItem function is provided to create brand-new menu items and also to add these items come a table that will be used later when determining which item come select. The function takes three arguments: name shows the surname of the choice (and is likewise used to brand it in the GUI), edge sets wherein on the ring the choice is centered, and selection sets how large the intake arc is.

*

The function very first creates a clone of the itemTemplate the was developed earlier. It likewise sets the position of the button based on angle. The duty also stores a 2D vector do from the input angle. This will certainly be used later on to compare with user entry to figure out which item is selected.

for ns = 1, NUM_OPTIONS dolocal angle = (360 / NUM_OPTIONS) * (i - 1)local name = "Option" .. InewMenuItem(name, angle, 360 / NUM_OPTIONS)endAfter the newMenuItem function is declared, the code then executes a loop to create the menu items. The continuous NUM_OPTIONS identify how countless menu choices to create. The angle for each items is identified by dividing 360 (the variety of degrees in a circle) by NUM_OPTIONS and then multiply by the present option. The selection is additionally determined by dividing 360 through NUM_OPTIONS. This values space all passed right into newMenuItem to create the button.

Opening the Menu

In this indict the food selection is toggled open and also closed through the left bumper. ContextActionService have the right to be used to tie this switch to a custom duty that opens and also closes the menu.

-- The food selection uses left bumper i m sorry the backpack also uses. Disabling backpack UI to stop conflictgame.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)local duty toggleMenu(actionName, inputState)if inputState == Enum.UserInputState.Begin thenopenMenu()elseif inputState == Enum.UserInputState.End thencloseMenu()endendContextActionService:BindAction("ToggleMenu", toggleMenu, false, Enum.KeyCode.ButtonL1)The default tennis2007.org regulate script binding the bumpers come toggle between items in the backpack. In order to rebind this input come the radial menu, the backpack UI needs to be disabled using StarterGui/SetCoreGuiEnabled. If you use a different input than the bumpers for her radial menu, you should be responsibility of the tennis2007.org defaults come prevent any conflicts.

The toggleMenu role is bound come the left bumper using ContextActionService/BindAction. ToggleMenu checks inputState to watch what state the bumper is in. If that is in the begin state, climate the user simply started pressing the bumper and also the menu needs to it is in opened. Otherwise, if the is in the end state, the menu needs to be closed.

local function openMenu()-- keep GuiNavigationEnabled and AutoSelectGuiEnabled and also then set both come falsewasGuiNavigationEnabled = GuiService.GuiNavigationEnabledwasAutoSelectGuiEnabled = GuiService.AutoSelectGuiEnabledGuiService.GuiNavigationEnabled = falseGuiService.AutoSelectGuiEnabled = false-- tie onThumbstickMoved functionContextActionService:BindAction("RadialMenu", onThumbstickMoved, false, Enum.KeyCode.Thumbstick1)-- make sure framework is visible and play opened animationmenuFrame.Visible = truemenuFrame:TweenSizeAndPosition(menuOpenSize, menuOpenPosition, Enum.EasingDirection.Out, Enum.EasingStyle.Quart, .5, true)menuOpen = trueendThe openMenu function needs to perform several things. First, it needs to disable GuiService/GuiNavigationEnabled and also GuiService/AutoSelectGuiEnabled and store the values so that they have the right to be restored later. These settings work-related well for other menu types, however are not well suited because that radial menus.


You may notice that the code only divides through the magnitude of the pass in vector (the position of the thumbstick) and also not by the size of the item’s vector. This is since the item’s vector is guarantee to be a unit vector, due to the fact that it to be made via Vector2.new(math.cos(angle), math.sin(angle)). A unit vector has actually a size of 1, therefore it can be for sure omitted from the divisor.

The angle in between the vectors is then compared to half the item’s range. If it is much less than fifty percent the item’s range, that means the thumbstick vector is somewhere in the arc defined for the item. If this is the case, getButtonFromVector returns the item’s button.

If getButtonFromVector return a button, onThumbstickMoved set the GuiService/SelectedObject to that button. This highlights the switch so the user to know it has actually been selected.

At the end of onThumbstickMoved, if the thumbstick was not pushed previous the deadzone, the SelectedObject is collection to nil to clear the selection.

Closing the Menu

When the food selection closes, the code needs to speak to a role based on the option that was selected (if any).

-- duty to speak to when items is selected. This is whereby you need to put your practice code-- come implement her menulocal function onMenuSelect(option)print(option, "selected")endlocal function closeMenu()-- restore GuiNavigationEnabled and also AutoSelectGuiEnabledGuiService.GuiNavigationEnabled= wasGuiNavigationEnabledGuiService.AutoSelectGuiEnabled = wasAutoSelectGuiEnabled-- Unbind onThumbstickMoved functionContextActionService:UnbindAction("RadialMenu")if GuiService.SelectedObject then-- If over there is a selection when the food selection closed, this is the alternative the user wantedonMenuSelect(GuiService.SelectedObject)end-- clear selected object and also play closeup of the door animationGuiService.SelectedObject = nilmenuFrame:TweenSizeAndPosition(menuClosedSize, menuClosedPosition, Enum.EasingDirection.Out, Enum.EasingStyle.Quart, .4, true,function()-- Callback function at finish of the animation. If the user hasn"t reopened the menu hide itif not menuOpen thenmenuFrame.Visible = falseendend)menuOpen = falseendThe closeMenu function an initial restores GuiNavigationEnabled and also AutoSelectGuiEnabled in case the remainder of the game relies on those settings. It also unbinds onThumbstickMoved so the the thumbstick can again be used for other purposes. Then, if there is a SelectedObject, the function calls onMenuSelect, pass in the SelectedObject together an argument.

onMenuSelect is where you will want to include any practice code. Based upon the switch that to be passed in, you deserve to write code for whichever action you require to take place when the switch is selected.

After onMenuSelect is called, closeMenu then removes the current an option and plays an animation to hide the menu.

See more: How Do You Reset The Anti Theft System On A Dodge Ram 1500 Anti Theft?

Complete Code

Below is every one of the password to carry out a radial food selection as checked out above. The code have to be in a LocalScript and also placed one of two people in StarterPlayerScripts or StarterGui.


local THUMBSTICK_DEADZONE = .4local RADIUS = .5local NUM_OPTIONS = 6local ANGLE_OFFSET = 90 -- Serviceslocal ContextActionService = game:GetService("ContextActionService")local GuiService = game:GetService("GuiService") -- The menu uses left bumper i beg your pardon the backpack likewise uses. Disabling backpack UI to avoid conflictgame.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false) neighborhood player = game.Players.LocalPlayerlocal menuItems = -- define position and size for the menu framework in both opened and closed stateslocal menuOpenPosition = UDim2.new(0.25, 0, 0.25, 0)local menuOpenSize = UDim2.new(0.5, 0, 0.5, 0)local menuClosedPosition = UDim2.new(0.5, 0, 0.5, 0)local menuClosedSize = UDim2.new(0.005, 0, 0.005, 0) -- define the element for the food selection optionslocal itemTemplate = Instance.new("TextButton")itemTemplate.Size = UDim2.new(0.3, 0, 0.2, 0)itemTemplate.AutoButtonColor = falseitemTemplate.TextScaled = true -- develop a screen and also frame because that the menulocal menuScreen = Instance.new("ScreenGui", player:WaitForChild("PlayerGui"))menuScreen.Name = "MenuScreen"local menuFrame = Instance.new("Frame", menuScreen)menuFrame.Size = menuClosedSizemenuFrame.Position = menuClosedPositionmenuFrame.Visible = falsemenuFrame.BackgroundTransparency = 1menuFrame.BorderSizePixel = 0menuFrame.Name = "MenuFrame" -- Storage for AutoSelectGuiEnabled and GuiNavigationEnabledlocal wasAutoSelectGuiEnabled = GuiService.AutoSelectGuiEnabledlocal wasGuiNavigationEnabled = GuiService.GuiNavigationEnabled local function newMenuItem(name, angle, range)local newItem = local button = itemTemplate:Clone()button.Text = namebutton.Name = namelocal angleRadians = math.rad(ANGLE_OFFSET + angle)button.Position = UDim2.new(.5 + RADIUS * math.cos(angleRadians) - button.Size.X.Scale / 2, 0, .5 - RADIUS * math.sin(angleRadians) - button.Size.Y.Scale / 2, 0)button.Parent = menuFramenewItem.Label = buttonnewItem.Vector = Vector2.new(math.cos(angleRadians), math.sin(angleRadians))newItem.Range = rangetable.insert(menuItems, newItem)end for ns = 1, NUM_OPTIONS dolocal edge = (360 / NUM_OPTIONS) * (i - 1)local name = "Option" .. InewMenuItem(name, angle, 360 / NUM_OPTIONS)end -- Goes v the menuItems table and also finds the angle between each item"s vector and-- the passed in vector. If the edge is less than half the item"s range, then that item-- is selected.local function getButtonFromVector(vector)for ns = 1, #menuItems dolocal items = menuItemslocal dotProduct = vector.X * item.Vector.X + vector.Y * item.Vector.Ylocal edge = math.acos(dotProduct / vector.magnitude)if edge = THUMBSTICK_DEADZONE then-- calculation the angle based on the place of the thumbsticklocal selectedButton = getButtonFromVector(inputObject.Position)GuiService.SelectedObject = selectedButtonelse-- Thumbstick inside deadzone, clean selectionGuiService.SelectedObject = nilendend -- function to call when item is selected. This is whereby you have to put your custom code-- come implement her menulocal role onMenuSelect(option)print(option, "selected")end local duty openMenu()-- store GuiNavigationEnabled and AutoSelectGuiEnabled and then set both come falsewasGuiNavigationEnabled = GuiService.GuiNavigationEnabledwasAutoSelectGuiEnabled = GuiService . AutoSelectGuiEnabledGuiService.GuiNavigationEnabled= falseGuiService.AutoSelectGuiEnabled = false -- bind onThumbstickMoved functionContextActionService:BindAction("RadialMenu", onThumbstickMoved, false, Enum.KeyCode.Thumbstick1) -- do sure frame is visible and also play opening animationmenuFrame.Visible = truemenuFrame:TweenSizeAndPosition(menuOpenSize, menuOpenPosition, Enum.EasingDirection.Out, Enum.EasingStyle.Quart, .5, true)menuOpen = trueend local role closeMenu()-- reclaim GuiNavigationEnabled and also AutoSelectGuiEnabledGuiService.GuiNavigationEnabled= wasGuiNavigationEnabledGuiService . AutoSelectGuiEnabled = wasAutoSelectGuiEnabled -- Unbind onThumbstickMoved functionContextActionService:UnbindAction("RadialMenu") if GuiService.SelectedObject then-- If over there is a selection when the menu closed, this is the choice the user wantedonMenuSelect(GuiService.SelectedObject)end -- clean selected object and also play closeup of the door animationGuiService.SelectedObject = nilmenuFrame:TweenSizeAndPosition(menuClosedSize, menuClosedPosition, Enum.EasingDirection.Out, Enum.EasingStyle.Quart, .4, true,function()-- Callback role at end of animation. If the user hasn"t reopened the menu hide itif not menuOpen thenmenuFrame.Visible = false end end ) menuOpen = false end local function toggleMenu(actionName, inputState)if inputState == Enum.UserInputState.Begin thenopenMenu()elseif inputState == Enum.UserInputState.End thencloseMenu()endend ContextActionService:BindAction("ToggleMenu", toggleMenu, false, Enum.KeyCode.ButtonL1)