local key = Enum.KeyCode.A
local o
game:GetService("UserInputService").InputBegan:Connect(function(obj)
if not o and obj.KeyCode == key then
o = obj
end
end)
Here is some code for a custom controller that I’ve written for one of my games. I put this in a local script named ‘Controller’ in ‘StarterPlayerScripts’. To see what it is doing you’ll have to know that I keep all my remote events/functions in a folder called ‘Connections’ in the workspace, with subfolders separating them into similar responsibilities. What this script does is listen to what inputs the server is interested in by ‘binding’ them to one or more ‘actions’. When the interesting keys are pressed, I send all the actions invoked back to the server.
local Input = game:GetService 'UserInputService'
local Players = game:GetService 'Players'
local connections = workspace.Connections[script.Name]
local keys = {}
local mouse = Players.LocalPlayer:GetMouse()
local function fire(actions, ...)
for action, TRUE in next, actions do
connections.act:FireServer(action, ...)
end
end
local function handle(input)
local key = input.KeyCode ~= Enum.KeyCode.Unknown and input.KeyCode or input.UserInputType
if keys[key] then
local act = input.UserInputState == Enum.UserInputState.Begin
if key == Enum.UserInputType.MouseButton2 then
Input.MouseBehavior = act and Enum.MouseBehavior.LockCurrentPosition or Enum.MouseBehavior.Default
end
if key == Enum.UserInputType.MouseButton1 then
fire(keys[key], act, mouse.Target)
else
fire(keys[key], act, input.Delta, input.Position)
end
end
end
Input.InputBegan:Connect(function(input, processed)
handle(input)
end)
Input.InputEnded:Connect(function(input, processed)
handle(input)
end)
Input.InputChanged:Connect(function(input, processed)
handle(input)
end)
function bind(key, action)
if keys[key] then
keys[key][action] = true
else
keys[key] = {[action] = true}
end
end
function unbind(key, action)
if keys[key] then
keys[key][action] = nil
end
end
connections.bind.OnClientEvent:Connect(bind)
connections.unbind.OnClientEvent:Connect(unbind)
connections.ready:FireServer()
Ah Okay, you are you probably looking for is the ContextActionService, which allows you to listen to individual keystrokes. It basically does what my codes does above without as much work. I choose not to use it because it filters out some keystrokes (if I remember correctly w, a, s, and d don’t fire).
Here’s a fun one. Using GetGamepadState(), you can actually get all the InputObjects for a given controller. InputObjects are mutable (i.e. they can change), which means you only have to call it once. From there, you can access the current input of a controller any time you want.
Here’s an example that throws all the inputs into a table using the KeyCode as the key:
local UIS = game:GetService("UserInputService")
-- Get input states and reference them based on the KeyCode:
local states = {}
for _,inputObj in pairs(gamepad1State = UIS:GetGamepadState(Enum.UserInputType.Gamepad1)) do
states[inputObj.KeyCode] = inputObj
end
-- Thumbstick input:
local leftThumbstick = states[Enum.KeyCode.Thumbstick1]
-- Output thumbstick position every second:
while (true) do
print("LeftThumbstick:", leftThumbstick.Position)
wait(1)
end
Edit: Apparently there’s a Changed event on InputObjects too, so using the leftThumbstick variable from the above example:
And my current method (the example code in the OP - which is also where that quote is from) caches the input object so I am aware that it can change (which is why I’m looking to get the InputObject)
Determining what is called before InputBegan, if anything, has a couple issues. First, it is a very small detail and may accidently change at some point. Second, determining which is faster may not always be reliable. Third, it is hard to tell without looking at Roblox source code or lots of testing… For most cases making a single handler that connects to all important input events and then decides which connection to run first is probably the way to go. If just two scripts need to be executed in the right order, have them communicate with each other using a custom event or the global table.
That being said, it could be that the UserInputService queues the InputBegan connection callbacks later in the game loop, so using RunService:BindToRenderStep(string name, int priority, function callback) with the proper priority (Enum.RenderPriority.Input, maybe +/- 1) would allow you to call GetKeysPressed and see them before the connected functions. If you don’t need the InputObject then you have a couple more options, like the Mouse object from different sources (player, tool, plugin).