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

7 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