Roblox GUI Maker
← All guides

Scripting

How to Open a GUI with a Key Press in Roblox

Press M for a map, B for a backpack, Tab for a leaderboard — key-press toggles are one of the most-asked GUI questions in Roblox. The mechanism is a single UserInputService event, but two details trip everyone up: the event also fires while the player is typing in a TextBox, and the toggle can end up on both client and server. This guide shows the full pattern done right, plus the gamepad-friendly variant.

Open the Main Menu template →

1. The core: UserInputService.InputBegan

UserInputService fires InputBegan for every key, tap, and button press on the client. Listen for it in a LocalScript, compare input.KeyCode to the key you want, and toggle the ScreenGui's Enabled property. That is the whole mechanism.

-- LocalScript under StarterGui
local UserInputService = game:GetService("UserInputService")

local player = game:GetService("Players").LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
local menuGui = playerGui:WaitForChild("MenuGui")

UserInputService.InputBegan:Connect(function(input, gameProcessed)
    if gameProcessed then return end
    if input.KeyCode == Enum.KeyCode.M then
        menuGui.Enabled = not menuGui.Enabled
    end
end)
Tip: gameProcessed is true when Roblox already consumed the input — the player is typing in a chat box or TextBox. Returning early there is what stops your menu from opening mid-sentence.

2. Which keys are safe to bind

Avoid keys Roblox or common games already own: W A S D and the arrows (movement), slash (chat), Escape (Roblox menu), and Enter. Letters like M, B, I, G, and K, plus Tab and Q, are popular and conflict-free choices. F-keys and Return often collide with platform UI.

Enum.KeyCode lists every bindable key and gamepad button — you can also bind Enum.KeyCode.ButtonX for controller users with the same InputBegan code.

3. Show and hide with a transition

Flipping Enabled is instant. If you want the menu to fade or slide, keep the GUI enabled and tween a property instead — a CanvasGroup's GroupTransparency for fades, or the panel's Position for a slide — then disable it after the close tween finishes.

local TweenService = game:GetService("TweenService")

local function openMenu()
    menuGui.Enabled = true
    local panel = menuGui:WaitForChild("Panel")
    TweenService:Create(
        panel,
        TweenInfo.new(0.2, Enum.EasingStyle.Quint, Enum.EasingDirection.Out),
        { GroupTransparency = 0 }
    ):Play()
end

4. Gamepad and mobile players

Keyboards are not the only input. For a bind that works across keyboard and controller with a free on-screen button, use ContextActionService: it maps one action name to several key codes, shows a mobile touch button automatically when you give it a title, and lets you unbind when the GUI closes.

local ContextActionService = game:GetService("ContextActionService")

local function handleOpen(actionName, inputState, input)
    if inputState ~= Enum.UserInputState.Begin then return end
    menuGui.Enabled = not menuGui.Enabled
end

ContextActionService:BindAction("OpenMenu", handleOpen, true, Enum.KeyCode.M, Enum.KeyCode.ButtonSelect)
ContextActionService:SetTitle("OpenMenu", "Menu")
Tip: The third argument to BindAction (true here) is createTouchButton — on phones Roblox shows a labeled round button that triggers the same handler.

5. Keep the toggle client-side

Opening your own menu is a visual change, so it belongs in a LocalScript — no RemoteEvent needed. What crosses to the server is only the consequence: if pressing the key buys something or claims a reward, that button inside the GUI fires a RemoteEvent and the server validates it, exactly like any other button.

Use this in your game

FAQ

Why does my GUI open when I type the letter in chat?

You are missing the gameProcessedEvent guard. The second parameter UserInputService passes your handler is true when Roblox already used the input (chat, TextBox). Start every handler with: if gameProcessed then return end.

How do I detect a key press on the server?

You don't — input only exists on the client. Detect it in a LocalScript and, if the server must react, fire a RemoteEvent. Never trust the client for rewards or permissions; validate there.

What is the difference between UserInputService and ContextActionService?

UserInputService reports raw input — one event, you filter the keys. ContextActionService binds named actions to several inputs at once, can create a mobile touch button, and supports priorities and re-binding. For a single key either works; for cross-platform menus ContextActionService is the better fit.

Can I let players choose their own keybind?

Yes — store the chosen Enum.KeyCode and compare against it instead of hardcoding. To capture the choice, listen for the next InputBegan after the player clicks a 'rebind' button and save input.KeyCode.

Related guides

Skip the boilerplate

Everything in this guide — the hierarchy, the layout helpers, the button wiring — is built into the free Roblox GUI maker. Drag, drop, tweak real Roblox properties, then export clean Luau you can paste straight into Studio.