Firstly, just want to make sure I clarify that this isn't a request for people to script for me, I'm just looking for advice on what I can do to implement this on my own.
For the past few months I've been struggling with trying to successfully create a system for player input. The reason I've labeled this as "advanced" is because this is not set up in the typical way that you would usually handle player input (listening for player event, checking if the input was the desired key, etcetera). I'm just looking for any advice someone can give me for implementing this kind of system into my game.
What I'm trying to achieve:
- An easy and efficient way of binding controls to an action (for example, a table filled with desired player input data; before people tell me to just use ContextActionService and
:BindAction(), this would be great, but unless I'm mistaken, all of the input data given can call the action individually, rather than all of them needing to be inputted at the same time) - (Optional, since this was my attempt) An object-oriented approach, where a "keybind" class is created and can easily be managed (editing the desired keybinds, checking for input states etcetera)
Current limitations:
- Hard to implement (there also aren't much resources around for this kind of thing; I don't know how 'good' developers handle their player input since there isn't much source code for that kind of thing either)
- Hard to implement with different input types, such as keyboard and mouse under the same action
- Keybinds with similar input data (for example, one action's keybind is simply just E, whereas another is LeftShift and E together) will also call the action, so some kind of priority system is needed??
Examples of current attempt:
I have a "Settings" module, which I'm using to store a table of the default controls for my game, which I would ideally like to have set up like this:
defaultControls = {
["Pickup"] = {Enum.UserInputType.MouseButton1},
["Centre"] = {Enum.KeyCode.R},
["Rotate"] = {Enum.KeyCode.LeftShift, Enum.KeyCode.E}
}
For each control, a module would then create a "KeyCode" object, which is stored in a "Controls" table on the client, unique to each player so they can easily be managed.
An example of the Keybind class:
function Keybind.new(name, action)
local self =
setmetatable(
{
_name = name,
_keyBind = action,
_isDown = false
},
Keybind
)
return self
end
I wanted an "isDown" property that external scripts can check to see if the keybind is currently being inputted, but I'm not entirely sure if this is a good idea yet.
The keybind then has a method called :IsDown(), which is called whenever any player input is made. The script iterates over the objects _keyBind table, which is a table of player input data as mentioned previously, and checks if all the keys are being pressed / inputted, along with any other inputs such as mouse, by using the :IsDown() method of UserInputService, which is great until you're also dealing with inputs that aren't just the keyboard.
Hypothetically if the class method worked, if :IsDown() was to return true, it would fire off a bindable event or something like that which an action handler can listen for and, well, handle.
But that's where I'm stuck at.
I'm all about code optimisation and efficiency, especially just for developing, because I want my games to be clean but also easy to make (I use a custom framework that I made based off of an old one I used to use and parts of the AeroGameFramework), but It's entirely possible that I'm too much of a perfectionist, and what I'm trying to set out to do is way too overkill and unnecessary, which is why I came here, either for some advice on how I can approach this, or for a reality check telling me that I'm just completely over-complicating everything for no reason.
