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.
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)
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
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)
Updating with an actual solution to the question for future fellow finders
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)