The fix probably caused a different issue: now the target function is executed when binding the action as well as when unbinding it. Repro (LocalScript):
local actSvc = game:GetService("ContextActionService")
function someAction()
print("Executing test function")
end
actSvc:BindAction("PressE", someAction, false, Enum.KeyCode.E)
wait()
actSvc:UnbindAction("PressE")
Output: ▶ Executing test function (x2)
The function was called 2 times despite the “E” key was never pressed.
You ARE getting the same result as me. The function someAction was called and printed “Executed” despite the fact that the actual key was never pressed.
Th at’s intended behavior. You need to check the state to see if it is being called with “Begin”, “End”, or “Cancel” to differentiate. Otherwise the function would run every time you pressed OR released the key.
This is how ContextActionService is meant to be used:
local function someAction(actionName, state, inputObject)
if state == Enum.UserInputState.Begin then
print("Key is pressed:", inputObject.KeyCode)
elseif state == Enum.UserInputState.End then
print("Key is released:", inputObject.KeyCode)
elseif state == Enum.UserInputState.Cancel then
print(actionName.." has been unbound")
end
end
cas:BindAction("PressE", someAction, false, Enum.KeyCode.R)
local actSvc = game:GetService("ContextActionService")
local player = game.Players.LocalPlayer
local char = player.Character
local light = script.Parent.ImageLabel
local function someAction(actionName, state, inputObject)
if state == Enum.UserInputState.Begin then
print("Key is pressed:", inputObject.KeyCode)
elseif state == Enum.UserInputState.End then
print("Key is released:", inputObject.KeyCode)
elseif state == Enum.UserInputState.Cancel then
print(actionName.." has been unbound")
end
local block = Instance.new("Part")
block.Name = "Block"
block.BrickColor = BrickColor.new("Cool yellow")
block.Size = Vector3.new(2, 2, 2)
block.Position = char.Head.Position + Vector3.new(0, -4.5, 0)
block.Parent = workspace
end
while true do
task.wait(5)
actSvc:BindAction("PressE", someAction, false, Enum.KeyCode.R)
light.Image = "http://www.roblox.com/asset/?id=13214238968"
task.wait(5)
actSvc:UnbindAction("PressE")
light.Image = "http://www.roblox.com/asset/?id=13214229273"
end
I am curious how it would be the intended behavior that a function cited in an unbindAction where the intent is to remove the mapped inputs that would trigger it should also result in that function being executed? I don’t recall this being documented behavior for the method, and it wasn’t occurring for the past year. This “fix” looks to have introduced a behavior breaking existing implementations, and I’m not sure I follow what use case should result in the deliberate unbinding of a context action (intended to prevent a function from being called by those inputs) should also result in that very function you’re unbinding to actually be called. That sounds counter intuitive and a break from how it’s been functioning for over a year.
I read through the documentation for UnbindAction (ContextActionService | Documentation - Roblox Creator Hub) and for UserInputState Cancel (UserInputState | Documentation - Roblox Creator Hub), and it says it’s only supposed to fire Cancel for in-progress input… but instead it now appears to always be firing the function 100% of the time on unbindAction, even when there was no input. That’s not been happening in the past year, and it now appears to be occurring since this fix, which suggests a bug was introduced.