Hello, fellow kids. I’ve been working on some fun features that should make ContextActionService a lot more attractive.
I’m sure we’ve all encountered the downsides of ContextActionService. You can’t use it with mouse clicks because it ALWAYS eats input, and you have almost no control over what takes precedence. And it’s totally unclear as to what’s even bound!
ContextActionResult
Now you can decide whether or not a bound action should sink or pass the input event, meaning other things (including other bound actions) can process it.
To use this, simply return Enum.ContextActionResult.Pass
in your callback function, and every action below it in the stack will get a chance to process it. It will also continue on to SurfaceGuis and the like, and it won’t make the second argument to UIS.InputBegan/Changed/Ended true. This requires no change to your existing code, because it will treat anything other than Pass as Enum.ContextActionResult.Sink
, including nil. It will also sink if you yield in your callback (i.e., you use wait()).
Here’s an example of this in action:
ContextActionService:BindAction("Bottom", function(actionName, inputState, inputObj)
if inputState == Enum.UserInputState.Begin then
print("Action named", actionName, "was fired!")
end
end, false, Enum.KeyCode.F, Enum.KeyCode.E)
ContextActionService:BindAction("Top", function(actionName, inputState, inputObj)
if inputState == Enum.UserInputState.Begin then
print("Action named", actionName, "was fired!")
end
if inputObj.KeyCode == Enum.KeyCode.E then
return Enum.ContextActionResult.Pass
end
end, false, Enum.KeyCode.F, Enum.KeyCode.E)
Pressing F will give you the following output:
Action named Top was fired!
Pressing E will give you the following output:
Action named Top was fired!
Action named Bottom was fired!
ContextActionPriority
You can also decide what priority to bind your action to; do you want it to be the lowest priority so it always remains when more contextual stuff comes and goes? Or do you want to make sure it always gets first dibs?
Now, all you have to do is use ContextActionService:BindActionAtPriority(actionName, callbackFunc, createTouchButton, priorityLevel, ...)
. That new argument, priorityLevel
, is an integer. It’s a little like BindToRenderStep in that there’s an Enum.ContextActionPriority
that provides sensible defaults spaced out by 1000.
All actions made with ContextActionService:BindAction
will default to a priority of Enum.ContextActionPriority.Default.Value
, or 2000. In the future, we plan on updating the default control scripts to use Enum.ContextActionPriority.Low.Value
in order to avoid accidentally overriding developer bindings to WASD and so on. You shouldn’t need to make any changes to your existing code, but let me know if something doesn’t work correctly.
Here’s a usage example:
ContextActionService:BindActionAtPriority("FirstOneBound", function(actionName, inputState, inputObj)
if inputState == Enum.UserInputState.Begin then
print("Action named", actionName, "was fired!")
end
end, false, Enum.ContextActionPriority.High.Value, Enum.KeyCode.F)
ContextActionService:BindActionAtPriority("SecondOneBound", function(actionName, inputState, inputObj)
if inputState == Enum.UserInputState.Begin then
print("Action named", actionName, "was fired!")
end
end, false, Enum.ContextActionPriority.Default.Value, Enum.KeyCode.F)
If you press F, you’ll see the following output:
Action named FirstOneBound was fired!
This is because FirstOneBound was bound at a higher priority level than SecondOneBound. Without this update, you would expect SecondOneBound to take precedence because it was bound later.
If you bind two actions at the same priority level, you’ll get the same old stack-based behavior, meaning none of your code needs to be updated to work after this update.
Action Bindings tab
To top it all off, you will now notice a new tab in the developer console when you hit F9. It’s called “Action Bindings” and it just provides a list of all the input types and keycodes currently bound to ContextActionService. If you click on one of the rows, it’ll expand to show you all of the actions that are binding that input type and what priority level they’re at. They’re sorted by priority, and actions that are bound by Roblox’s CoreScripts will appear in italics with a red background.
Hope it helps!