Multiple Key binding possible with ContextActionService?

Hi all,

I want to perform multi-key controlled actions (so things like holding shift + W to sprint forward), but is this possible with ContextActionService? I have tried the following:

local CAS = game:GetService("ContextActionService")

local function walk(actionName, inputState:Enum.UserInputState)
	if inputState == Enum.UserInputState.Begin then 
		print("Walking")
	end
end

local function sprint(actionName, inputState:Enum.UserInputState)
	if inputState == Enum.UserInputState.Begin then 
		print("Sprinting")
	end
end

CAS:BindAction("sprint", sprint, false, Enum.KeyCode.LeftShift, Enum.KeyCode.W)
CAS:BindAction("Walking", walk, false, Enum.KeyCode.W)

This does not work because only Leftshift binds to “sprint” action, rather than Leftshift + W.

Any workarounds for this problem? Thanks!

Nvm, I figured it out. For those who are curious, you can do something similar to this:

local CAS = game:GetService("ContextActionService")

local activeKeycodes: {Enum.KeyCode} = {}

local function walkAndSprint(actionName, inputState:Enum.UserInputState, inputObject: InputObject)
  local keycode = inputObject.KeyCode
	if inputState == Enum.UserInputState.Begin then 
		table.insert(activeKeycodes, keycode)
    local leftShift = table.find(activeKeycodes, Enum.KeyCode.LeftShift) 
    local w = table.find(activeKeycodes, Enum.KeyCode.W)
    if leftShift and w then
      print("Sprinting")
    elseif w then
      print("Walking")
    end
  elseif inputState == Enum.UserInputState.End then
    table.remove(activeKeycodes, table.find(activeKeycodes, keycode))
	end
end


CAS:BindAction("sprint", walkAndSprint, false, Enum.KeyCode.LeftShift, Enum.KeyCode.W)
1 Like

While this may get the job done it’s a complete mess. Try using UserInputService to see if your keys are pressed at the same time instead of all this table.* nonsense.

Edit: props to you for sharing your solution, more people need to adopt this etiquette

2 Likes

Thanks for the reply - can I ask if there is a method in UserInputService that tracks keys that are pressed at the same time?

You’re right that the code is kinda clunky and needs to be refactored

UserInputService:IsKeyDown(x) and UserInputService:IsKeyDown(y)
should work

local Game = game
local UserInputService = Game:GetService("UserInputService")

local Inputs = {LeftShift = "W", W = "LeftShift"}

local function OnInputBegan(InputObject)
	local Input = InputObject.KeyCode.Name
	if not Inputs[Input] then return end
	if not UserInputService:IsKeyDown(Inputs[Input]) then return end	
	print("Sprinting!")
end

local function OnInputEnded(InputObject)
	local Input = InputObject.KeyCode.Name
	if not Inputs[Input] then return end
	print("Not sprinting!")
end

UserInputService.InputBegan:Connect(OnInputBegan)
UserInputService.InputEnded:Connect(OnInputEnded)
3 Likes

Updating with an actual solution to the question for future fellow finders :slight_smile:

Blockquote
Action bindings behave like a stack: if two actions are bound to the same user input, the most recently bound action handler will be used.

To allow other binded functions to trigger in succession, return Enum.ContextActionResult.Pass .

Example code:

local function actionHandler(...) : Enum.ContextActionResult
		bindFunction(...)
		return Enum.ContextActionResult.Pass
	end

	CAS:BindAction(actionName,actionHandler,createButton,key)

Source: ContextActionService | Documentation - Roblox Creator Hub

Never mind, that wasn’t the question I guess.