If I understand right, you’re trying to make an input mapping system? Where you can select an input and then press a button to rebind it? But you don’t want to trigger the functionality of that key when you do so?
yea, pretty much. i have a TextButton, then when I click that TextButton, it waits for me to press a key, then it sets the keybind to that new key. and yea, i don’t want to invoke the function once i set the keybind.
So this is the method that I use to get the key pressed. It’s not my intention to hand over code, however, I figured I’d include this here so you could see the method I use to do so. It’s already in a module so hypothetically speaking it should be copy and paste.
-- Services
local UserInputService = game:GetService("UserInputService")
local ContextActionService = game:GetService("ContextActionService")
-- Reference
local module = {}
local isListeningForInput = false
function module:GetNextKey(inputType)
assert(isListeningForInput == false, "InputMap:GetNextKey() can only initiate one session at a time.")
if isListeningForInput then return end -- We can only listen for one key at a time.
isListeningForInput = true -- Debounce.
print("Listening for key input.")
local connection = nil
local bindableEvent = Instance.new("BindableEvent")
local Disconnect = function()
if not connection then return end
connection:Disconnect() -- Stop listening for key presses.
bindableEvent:Destroy() -- Destroy bindable event for cleanup.
isListeningForInput = false -- Allow a new session to be created.
end
connection = UserInputService.InputEnded:Connect(function(inputObject, gameProcessed)
local keyCode = inputObject.KeyCode
if gameProcessed then
Disconnect()
return
end
if inputObject.UserInputType ~= inputType then return end
if keyCode == Enum.KeyCode.Escape or keyCode == Enum.KeyCode.ButtonB then Disconnect() return end
local modifiers = {
["LeftControl"] = UserInputService:IsKeyDown(Enum.KeyCode.LeftControl),
["LeftAlt"] = UserInputService:IsKeyDown(Enum.KeyCode.LeftAlt),
["LeftShift"] = UserInputService:IsKeyDown(Enum.KeyCode.LeftShift),
["RightShift"] = UserInputService:IsKeyDown(Enum.KeyCode.RightShift),
["RightControl"] = UserInputService:IsKeyDown(Enum.KeyCode.RightControl),
["RightAlt"] = UserInputService:IsKeyDown(Enum.KeyCode.RightAlt)
}
print("Listened and found key", keyCode)
bindableEvent:Fire(keyCode, modifiers)
Disconnect()
end)
return bindableEvent.Event
end
--[[
local keyCode1, modifiers1 = module:GetNextKey(Enum.UserInputType.Keyboard):Wait()
ContextActionService:BindAction("TestBind", function(actionName, inputState, inputObject)
print("We binded to", inputObject.KeyCode)
print("The key that was pressed is", inputObject.KeyCode, modifiers1)
end, false, keyCode1)
]]--
--[[
Example 1
-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Reference
local Retro = require(ReplicatedStorage:WaitForChild("Retro.Client"))
local InputMap = Retro.InputMap
local KeyCode, Modifiers = InputMap:GetNextKey(Enum.UserInputType.Keyboard):Wait()
print("The key that was pressed is", KeyCode, Modifiers)
Example 2
-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Reference
local Retro = require(ReplicatedStorage:WaitForChild("Retro.Client"))
local KeyCode, Modifiers = Retro.InputMap:GetNextKey(Enum.UserInputType.Keyboard):Wait()
print("The key that was pressed is", KeyCode, Modifiers)
]]--
return module
It creates a bindable event. A BindableEvent works only on the context it’s called from. So if you use it on a local script it only works in local scripts and if you use it on the server then it only works on the server.
When I want to get the next key pressed, I call a function that connects to the UserInputService.InputEnded event. It then caches the RobloxScriptSignal as the variable connection.
Afterward, it creates the bindable event and returns the event. Once you press a key, the event is then fired and the RobloxScriptSignal for UserInputService.InputEnded is disconnected to prevent any more key strokes from being mapped.
local KeyCode, Modifiers = Retro.InputMap:GetNextKey(Enum.UserInputType.Keyboard):Wait()
So here I connect to the bindable event that’s returned and wait for it to be fired. Once it’s fired KeyCode and Modifiers are populated.
You can then call ContextActionService:BindAction() with the KeyCode that’s returned. You can ignore Retro.InputMap that’s basically the module that’s returned at the end of the module script.
Modifiers just return a list of keys I consider to be modifiers. The keys in the table are true if the button was pressed down at the time of mapping. (Modifiers are unfinished so… I can’t guarantee anything lol)
Retro is the custom framework my game runs on. You don’t need it. I use it to get the module script from my framework without having to make a bunch of variables.
To use the modifiers properly you can check if a particular modifier is down when you bind the action using UserInputService:IsKeyDown. It lets you do things like hold alt and press Q for instance.
aight, looks like I’ve solved it. In the function (which is basically the 2nd argument in CAS:BindAction()), you need to check if your input state is equal to Enum.UserInputState.Begin, before running any code.
Example:
local function funcName(actionName, inputState, inputObject)
if inputState == Enum.UserInputState.Begin then
-- run code
end
end