ContextActionService:GetButton() yields forever

ContextActionService:GetButton() will yield forever when trying to grab a button created through :BindAction(). This issue occurs consistently when emulating mobile devices in Studio. This issue does not happen when device emulation is disabled (I assume because the buttons don’t need to be created on PC).

Reproduction Steps:
Open a Roblox Studio place, add a local script to StarterPlayerScripts, paste in the following code, and play-test the game while emulating a mobile device.

local ContextActionService = game:GetService("ContextActionService")

local function onAction(actionName, inputState, inputObj)
	if inputState == Enum.UserInputState.Begin then
		print("Input began!", actionName)
	elseif inputState == Enum.UserInputState.End then
		print("Input ended!", actionName)
	end
	return Enum.ContextActionResult.Pass
end

ContextActionService:BindAction("ExampleAction1", onAction, true, Enum.KeyCode.P, Enum.UserInputType.Touch, Enum.UserInputType.MouseButton1)
ContextActionService:BindAction("ExampleAction2", onAction, true, Enum.KeyCode.P, Enum.UserInputType.Touch, Enum.UserInputType.MouseButton1)

local thread = coroutine.running()
task.defer(function()
	while true do
		print(coroutine.status(thread))
		task.wait(1)
	end
end)
print("before GetButton call")
local button = ContextActionService:GetButton("ExampleAction1")
print("after GetButton call")
if button then
	button:SetTitle("Example Action 1")
end

The coroutine executing the script will remain suspended. The print call after :GetButton() is never reached!

Expected behavior

I expect :GetButton() to return the button that has been created or return nil if no such button exists for the specified action name. It should not yield forever as it causes unexpected problems in my scripts.

A private message is associated with this bug report

6 Likes

Supporting this - issue is still present. Might also apply to live games now, for those in use of mobile devices.

What I’m basically trying to do is grab the dependencies from a context button and size them equally to the JumpButton created during runtime, yet it’s never getting past that function call.

2 Likes

I hope that’s not the case when even after years they won’t fix it.

I saw cases like that.

1 Like

This should fix it. Paste it and tell me if it works.

local ContextActionService = game:GetService("ContextActionService")

local function onAction(actionName, inputState, inputObj)
	if inputState == Enum.UserInputState.Begin then
		print("Input began!", actionName)
	elseif inputState == Enum.UserInputState.End then
		print("Input ended!", actionName)
	end
	return Enum.ContextActionResult.Pass
end

ContextActionService:BindAction("ExampleAction1", onAction, true, Enum.KeyCode.P, Enum.UserInputType.Touch, Enum.UserInputType.MouseButton1)
local PlrGui = game.Players.LocalPlayer.PlayerGui
local UIS = game:GetService("UserInputService")
if UIS.TouchEnabled then
	PlrGui:WaitForChild("ContextActionGui")
end
ContextActionService:BindAction("ExampleAction2", onAction, true, Enum.KeyCode.P, Enum.UserInputType.Touch, Enum.UserInputType.MouseButton1)

local thread = coroutine.running()
task.defer(function()
	while true do
		print(coroutine.status(thread))
		task.wait(1)
	end
end)
print("before GetButton call")
local button = ContextActionService:GetButton("ExampleAction1")
print("after GetButton call")
if button then
	button:SetTitle("Example Action 1")
end