Context Action Fires When Opening Settings Menu

I want my context action to fire when either Keycode.One is pressed or Keycode.DPadUp is pressed. I have achieved this using this code in a LocalScript.

local CAS = game:GetService("ContextActionService")

CAS:BindAction("HelloWorld", function(EventName, InputState, InputObject)
	print("EventName: "..EventName.." | InputState: "..tostring(InputState).." | InputObject: "..tostring(InputObject))
end, false, Enum.KeyCode.One, Enum.KeyCode.DPadUp)

Although I get my desired behavior with this code, I have created a bug. If I press Esc and then click on the Settings menu, my context action fires somehow.

Output from intended behavior (1 press of the One key):
EventName: HelloWorld | InputState: Enum.UserInputState.Begin | InputObject: InputObject

EventName: HelloWorld | InputState: Enum.UserInputState.End | InputObject: InputObject

Output from unintended behavior (Pressing Esc and clicking on Settings once):
EventName: HelloWorld | InputState: Enum.UserInputState.Cancel | InputObject: InputObject

Interestingly, this behavior stops if I remove Enum.Keycode.DPadUp from the parameters of my “HelloWorld” BindAction. Should I be handling gamepad input differently to avoid this behavior?

The unintended behavior causes an UserInputState called Cancel. I’m not entirely sure what that means as well, if someone could explain that it would be nice.

3 Likes

@Defegne me personally use UserInputService

local player = game.Players.LocalPlayer
local UIS = game:GetService("UserInputService")

UIS.InputBegan:Connect(function(Keycode)
	if Keycode.KeyCode == Enum.KeyCode.One then
		print("One was pressed")
	else
		print("not touched")
	end
end)
UIS.InputEnd:Connect(function(Keycode)
	if Keycode.KeyCode == Enum.KeyCode.One then
		print("One was pressed")
	else
		print("not touched")
	end
end)


UIS.InputBegan:Connect(function(Keycode)
	if Keycode.KeyCode == Enum.KeyCode.DPadUp then
		print("One was pressed")
	else
		print("not touched")
	end
end)
UIS.InputEnd:Connect(function(Keycode)
	if Keycode.KeyCode == Enum.KeyCode.DPadUp then
		print("One was pressed")
	else
		print("not touched")
	end
end)
1 Like

If I used UserInputService, then I wouldn’t be able to type “1” in the chat without it firing then right?

Weird thing is that my issue only happens when I try to use DPadUp as a parameter. If I remove that then it works fine.

2 Likes

@EnqryptedAPI

  1. Your code would still fire because you don’t filter out input if it’s listened to internally.
  2. That is not the purpose of MessagingService. Please do not suggest things without knowing what they do.

ContextActionService, if I recall correctly, does not have a way to void input that is listened to internally. That’s why UserInputService works better if you need that check explicitly.

local UserInputService = game:GetService("UserInputService")

UserInputService.InputBegan:Connect(function (InputObject, GameProcessedEvent)
    if not GameProcessedEvent then
        print(InputObject.KeyCode)
    end
end)

This will prevent yor input from firing when a keybind is listening to an internal keybind.

2 Likes

I noticed that the UserInputState for the unintended behavior is “Cancel”. If I add an if statement to my handler function that accepts only “Begin” or “End”, then I’ll be able to achieve my intended behavior still, right?

I really want to use ContextActionService over UserInputService because it seems a lot more convenient and beginner friendly. Is that advisable?

You have to compare the UserInputState passed into the function to make sure you’re not listening to the Cancel user input state.

This would make the action only listen to UserInputState.Begin

local CAS = game:GetService("ContextActionService")

CAS:BindAction("HelloWorld", function(EventName, InputState, InputObject)
	if InputState == Enum.UserInputState.Begin then
		print("EventName: "..EventName.." | InputState: "..tostring(InputState).." | InputObject: "..tostring(InputObject))
	end
end, false, Enum.KeyCode.One, Enum.KeyCode.DPadUp)

If you want to shorten the comparison, you can also use the Enum’s name:

if InputState.Name == "Begin" then --...

It looks like Cancel is fired whenever a Roblox gui is meant to process input. You can probably use this as a way to close other gui’s if they protrude.

2 Likes

Ah okay,i didnt mean MessagingService,you can see if Esc was pressed