Binding ContextActionService's Actions question

Hey!

I’m working on a system that allows players to customize their keybindings for various in-game actions in my Roblox game. To achieve this, I plan to use DataStoreService to save these keybinding preferences. However, I’ve encountered a hurdle – I can’t seem to save Enums like Enum.KeyCode.E .

So I’ve been exploring various solutions, and here’s what I’ve come up with:

I’ve been using ContextActionService to bind actions, and I noticed that when I bind an action with no keys, like this:

ContextActionService:BindAction("Action1", actionFunction, true, nil)

I get this error:

ContextActionService:BindAction called with an invalid hotkey (should be either Enum.KeyCode, Enum.UserInputType, or string)

This error message suggests that I can bind a key using a string, right? Since strings can be saved in DataStore, I decided to experiment with it. Some strings like “e,” “w,” and “h” seem to work:

ContextActionService:BindAction("Action1", actionFunction, true, "e", "w", "h")

However, my question is: Is there a comprehensive list of strings that are valid for binding keys using ContextActionService? I’ve looked through the ContextActionService documentation, but I couldn’t find such a list. I’d like to know if this approach is a viable solution for my keybinding customization system or if there’s a better method out there.

Does anyone have insights or know where I can find this information?

Thank you for your help!

1 Like

I’m not sure if I understood your question correctly, but you can just type Enum.KeyCode. to see valid keycodes via autocomplete.

each keycode has a number value so you could just save the number in the datastore and use it when binding

you can find them here

1 Like

Thanks to this guy, I understood your question.

Just use @aleksinoobz’s solution.

1 Like

Like this?

local ContextActionService = game:GetService("ContextActionService")

local function actionFunction()
	print(1)
end

ContextActionService:BindAction("Action1", actionFunction, true, Enum.KeyCode.E.Value)

No, just the number of the keycode
You can find them in the link in my other reply

Oh, I’m sorry. So, it’s like this?

local ContextActionService = game:GetService("ContextActionService")

local function actionFunction()
	print(1)
end

ContextActionService:BindAction("Action1", actionFunction, true, 101)

Did you mean that I should save the number of the enum in the data store and then, when a player joins, retrieve the corresponding enum using that number saved in the data store?

Store the Enum value in an intvalue and store that in datastore.

This makes sense. And when a player joins, can I find the Enum that corresponds to this number so I can bind and action with it?

You only need to pass the number of the intvalue. No need for checking the enum.

This also applies to every other Enum.

Like this? (Using 101 as the value of Enum.KeyCode.E)

ContextActionService:BindAction("Action1", actionFunction, true, 101)

I don’t think you can bind an action using a number, just use Enum.KeyCode

local ContextActionService = game:GetService("ContextActionService")

local function actionFunction()
	print(1)
end

ContextActionService:BindAction("Action1", actionFunction, true, Enum.KeyCode.E)

Hi, I did not understand what you meant, could you please explain it to me?

Thank you for explaining :grin:

That’s what I wanted to do, but I can’t save Enums to DataStore; that was the issue.

Do you have any solutions to the question I asked above?

Why can’t you just store the enum name in the data store?

Enum.KeyCode.E.Name

And to load it

Enum.KeyCode[How ever you stored it]
1 Like

Yes, 101 is indeed the correct value for E.

It’s absolutely fine to use Enum values when inserting Enums.

I’ve done something like this. The problem is that you have to search the Enum.Keycode for the specific value to get the Enum back.

-- Returns the Enum.Keycode Enum from the given value.
local function getEnumKeycode(value)
	for _, enum in pairs(Enum.Keycode:GetEnumItems()) do
		if enum.Value == value then
		return enum
	end
end

Something like that.

A much faster way would be to construct a lookup table before hand. The instead of searching for an Enum in a loop, the time is reduced to a table lookup.

local EnumKeycodeTable = {}

-- Construct Enum.Keycode lookup table.
local function constructEnumKeycode()
	for idx, enum in pairs(Enum.Keycode:GetEnumItems()) do
		EnumKeycodeTable[idx] = enum
	end
end

Then to use the table, it’s just local variable = EnumKeycodeTable[value]. So when you load the player’s data, just convert the values back into Enum using the table. ContextActionService REQUIRES the Enum for key binding. constructEnumKeycode() must be used when the server first starts up so the table is available when the players log in.

1 Like

I think this would work!

The only issue is that I’ll have to check whether the Enum is a KeyCode or a UserInputType, but I think a simple if statement would solve this.

Thank you so much for your help!

1 Like