Recently, I have been trying to get back into luau coding in roblox. Over summer, I learned how to compact and modulize things, via oop, computational thinking, etc. However, I have come to a great realizing. I know all the syntax, but, I code very straightforward. I was trying to make a UIS wrapper, and my plan was to just simply do something like this:
function input.new(key:Enum.KeyCode, hold:boolean, hold_duration:number?)
local self = setmetatable({}, input)
self._key = key
self._hold = hold
self._hold_duration = hold_duration or 1
return self
end
function input:check_device()
return UIS:GetLastInputType()
end
function input:input_began(inp, gp)
if (inp.KeyCode == self._key) and (self._hold == false) then
return true
elseif (inp.KeyCode == self._key) and (self._hold == true) then
return false
end
end
Now I understand this isnât ACTUALLY what I would really do for this, but it just gets my idea across. However, after searching for references, and a little help from AI, I saw a UIS wrapper that I didnât understand. As I said earlier, I understood all the syntax. But, it really just made me feel less of a programmer. Because I code so straight-forward, and I dont do well with systems. Here is said code:
local actions = {}
local connections = {}
local enabled = true
local function matchesBind(inputObject, bind)
if bind.EnumType == Enum.KeyCode then
return inputObject.KeyCode == bind
elseif bind.EnumType == Enum.UserInputType then
return inputObject.UserInputType == bind
end
end
local function fireAction(action, state, inputObject)
action.callback(state, inputObject)
end
local function onInputBegan(inputObject, gameProcessed)
if gameProcessed or not enabled then return end
for _, action in pairs(actions) do
for _, bind in ipairs(action.keybinds) do
if matchesBind(inputObject, bind) then
action.held = true
fireAction(action, Enum.UserInputState.Begin, inputObject)
break
end
end
end
end
local function onInputEnded(inputObject, gameProcessed)
if not enabled then return end
for _, action in pairs(actions) do
if not action.held then continue end
for _, bind in ipairs(action.keybinds) do
if matchesBind(inputObject, bind) then
action.held = false
fireAction(action, Enum.UserInputState.End, inputObject)
break
end
end
end
end
function Input.Bind(actionName, keybinds, callback)
assert(type(actionName) == "string", "Action name must be a string")
assert(type(keybinds) == "table", "Keybinds must be a table")
assert(type(callback) == "function", "Callback must be a function")
if actions[actionName] then
warn("Action already bound:", actionName)
return
end
actions[actionName] = {
keybinds = keybinds,
callback = callback,
held = false
}
end
function Input.Unbind(actionName)
actions[actionName] = nil
end
function Input.Enable()
enabled = true
end
function Input.Disable()
enabled = false
-- Force-release all held inputs
for _, action in pairs(actions) do
if action.held then
action.held = false
action.callback(Enum.UserInputState.End, nil)
end
end
end
function Input.Clear()
table.clear(actions)
end
connections.InputBegan =
UserInputService.InputBegan:Connect(onInputBegan)
connections.InputEnded =
UserInputService.InputEnded:Connect(onInputEnded)
function Input.GetLastInputType()
return UserInputService:GetLastInputType()
end
return Input
return input
All Iâm asking is for direction on how I can learn to code this systematically-and if possible-help me break this code down and understand it so I can use it in the future. Because its like I code without a mental model. I just apply the syntax that I know-no further thought. Any help is appreciated ![]()