MasterInputManager | Advanced Keybind System with Priority, Input Sinking & Multi-Key Support

Hello! since Roblox’s new Input System got released i figured ill edit my keybind manager code to fit the public and release this, this uses UserInputService and ContextActionService and is basically a wrapper of both, using this module is literally up to you, but i find it very easy, performant and clean to use in a framework, so ill release this for the public

This module has alot of what the new Input Action System has, but just not all.
Let me know if you want anything added and if i can i will add as im using this in my own game.

Features:

  • Multi-key combinations - Support for complex keybinds like “Ctrl+Shift+E”
  • Mouse button support - Easy aliases (LMB, RMB, MMB, MB1, MB2, MB3) for mouse inputs
  • Full gamepad support - All controller buttons, triggers, and thumbsticks
  • Priority system - Higher priority keybinds will fire before the others
  • Input sinking - Prevent keybinds from firing and override Roblox’s Built-in functions
  • Strict order mode - Keys must be pressed in exact sequence
  • Game processed filtering - Optionally ignore inputs when chat/UI is focused
  • Multi-keybind creation - Create multiple keybinds from a single call ({‘E+Q’,‘ButtonA+ButtonY’,‘LMB+RMB’})
  • No Infinite Connections - Instead of creating a new connection for every keybind you create, it uses a single master connection that handles all input detection.
  • Clean/Noob Friendly API
API
--[[
	MasterInputManager
	
	By: ltsRealJr
	
	Version: 0.0.1
	
	Constructor:
	    KeybindManager.new(KeysInput: string | table, Callback: function): Keybind
	        - KeysInput: Key combination as string ('Q', 'Ctrl+E') or table of keys
	        - Callback: Function called when keybind triggers (Pressed: boolean, Released: boolean, Held: boolean) -> ()
	
	Methods:
	    :SetPriority(Priority: number)
	        - Sets keybind priority (higher = executes first)
	    
	    :SinkInput(Sink: boolean)
	        - Prevents lower priority keybinds from firing when this one is active
	    
	    :StrictOrder()
	        - Requires keys to be pressed in exact sequence
	    
	    :UnstrictOrder()
	        - Allows keys to be pressed in any order (default)
	    
	    :IgnoreGP()
	        - Ignores game processed state (fires even when chat/GUI focused)
	    
	    :UnignoreGP()
	        - Respects game processed state (default)

	    :Enable()
	        - Enables the keybind
	    
	    :Disable()
	        - Disables the keybind temporarily
	    
	    :Rebind(NewKeysInput: any)
	        - Changes the key combination for this keybind
	    
	    :Destroy(): ()
	        - Permanently destroys the keybind and cleans up resources

	    :RegisterCAS()
	        - Enables ContextActionService for this keybind
	    
	    :UnregisterCAS()
	        - Disables ContextActionService for this keybind

	    :IsHeld(): boolean
	        - Returns true if the keybind is currently being held down

	Properties: (These return within the callback function)
	    .IsHeld: {Value: boolean}
	        - Current held state of the keybind
	    
	    .Pressed: {Value: boolean}
	        - Current pressed state (momentary)
	    
	    .Released: {Value: boolean}
	        - Current released state (momentary)

	Examples:

	Basic Usage:
		local MasterInputManager = require(script.MasterInputManager)
		
		local JumpKeybind = MasterInputManager.new('Space', function(Pressed, Released, Held)
		    if Pressed then
		        Character.Humanoid.Jump = true
		    end
		end)
		
	Key Combinations:
		local AdminKeybind = MasterInputManager.new('Ctrl+Shift+A', function(Pressed, Released, Held)
		    if Pressed then
		        OpenAdminPanel()
		    end
		end)
		
	With Priority and Input Sinking:
		local MenuKeybind = MasterInputManager.new('M', function(Pressed, Released, Held)
		    if Pressed then
		        ToggleMenu()
		    end
		end):SetPriority(1000):SinkInput(true)
		
	Multi-Key Keybinds: (These will all trigger the same callback if pressed)
		local WeaponKeybind = MasterInputManager.new({'Q', 'E', 'R'}, function(Pressed, Released, Held)
		    if Pressed then
		        SelectWeapon()
		    end
		end)
		
	Strict Order Mode:
		local ComboKeybind = MasterInputManager.new('Q+W+E', function(Pressed, Released, Held)
		    if Pressed then
		        ExecuteCombo()
		    end
		end):StrictOrder()
		
	Method Chaining:
		local AdvancedKeybind = MasterInputManager.new('F', WeaponCallback)
		    :SetPriority(50)
		    :SinkInput(false)
		    :IgnoreGP()
		    :Enable()
		
	Dynamic Rebinding:
		local Keybind = MasterInputManager.new('Q', Callback)
		Keybind:Rebind('E') -> Now responds to E instead of Q
		
	State Monitoring:
		local Keybind = MasterInputManager.new('LeftShift', function(Pressed, Released, Held)
		    if Held then
		        IncreaseWalkSpeed()
		    else
		        NormalWalkSpeed()
		    end
		end)
		
	External State Checking:
		local SprintKeybind = MasterInputManager.new('LeftShift', function() end)
		
		if SprintKeybind:IsHeld() then
		    IncreaseWalkSpeed()
		else
		    NormalWalkSpeed()
		end
]]

MasterInputManager.rbxm (7.7 KB)

Example Usage:

local MasterInputManager = require(path.to.MasterInputManager)
		
		local JumpKeybind = MasterInputManager.new('Space', function(Pressed, Released, Held)
		    if Pressed then
		        Character.Humanoid.Jump = true
		    end
		end)
		
	Key Combinations:
		local AdminKeybind = MasterInputManager.new('Ctrl+Shift+A', function(Pressed, Released, Held)
		    if Pressed then
		        OpenAdminPanel()
		    end
		end)
		
	With Priority and Input Sinking:
		local MenuKeybind = MasterInputManager.new('M', function(Pressed, Released, Held)
		    if Pressed then
		        ToggleMenu()
		    end
		end):SetPriority(1000):SinkInput(true)
		
	Multi-Key Keybinds: (These will all trigger the same callback if pressed)
		local WeaponKeybind = MasterInputManager.new({'Q', 'E', 'R'}, function(Pressed, Released, Held)
		    if Pressed then
		        SelectWeapon()
		    end
		end)
		
	Strict Order Mode:
		local ComboKeybind = MasterInputManager.new('Q+W+E', function(Pressed, Released, Held)
		    if Pressed then
		        ExecuteCombo()
		    end
		end):StrictOrder()
		
	Method Chaining:
		local AdvancedKeybind = MasterInputManager.new('F', WeaponCallback)
		    :SetPriority(50)
		    :SinkInput(false)
		    :IgnoreGP()
		    :Enable()
		
	Dynamic Rebinding:
		local Keybind = MasterInputManager.new('Q', Callback)
		Keybind:Rebind('E') -> Now responds to E instead of Q
		
	State Monitoring:
		local Keybind = MasterInputManager.new('LeftShift', function(Pressed, Released, Held)
		    if Held then
		        IncreaseWalkSpeed()
		    else
		        NormalWalkSpeed()
		    end
		end)
11 Likes