ContextActionService not working on mobile

I recently noticed while making a long annoying interaction script, that using RunService to Bind and Unbind ContextActionService functions creates the problem where it works properly for PC but doesn’t work at all for mobile.

Small script example showcasing the problem:

RunService = game:GetService("RunService")
CAS = game:GetService("ContextActionService")

function ClickInteract(actionName, inputState)
	if inputState == Enum.UserInputState.Begin then
		print("something cool")
	end
end

RunService.Heartbeat:Connect(function()
	
	CAS:BindAction("Interact",ClickInteract,true, Enum.KeyCode.C)
	CAS:SetPosition("Interact", UDim2.new(1, -70, 0, 10))
	
end)

How do I make this work properly for mobile?

Why do need to put that in a Heartbeat loop???

Just Bind the action normally without a H E A R T B E A T loop.

Its just an example, the actual script uses the loop to know when a player is near an object.

Don’t use a loop to bund the action, that’s completely unnecessary.

Instead, you should use an event, and check if the player is near an object.

My only option is to use a loop since the interactive script needs to always check what objects the player is near, when they’re close enough the action is binded and when they arent the action is unbinded.

Heres the actual script:

local plr = game.Players.LocalPlayer

repeat wait() until plr.Character

--Services--
local runService = game:GetService("RunService")
local CAS = game:GetService("ContextActionService")
local storage = game:GetService("ReplicatedStorage")
local RemoteEvents = storage:WaitForChild("RemoteEvents")

--Locals--

local char = plr.Character
local plrPosition = char.PrimaryPart.Position
local hrp = char:WaitForChild("HumanoidRootPart")
local InteractiveImage = script:WaitForChild("InteractiveImage")

--Bools--

local Interactive = nil
local DB = true

--[[=============================================================================================
						I N T E R A C T I V E  M A I N S C R I P T
===============================================================================================]]

local radius = 7

--[[----------------------------------------
			   Interactive Sorter
-------------------------------------------]]--

local function GetCloseInteractives(PartsNearPlayer)
	
	local CloseInteractives = {}
	
	---- Get Parts Near Player ----	

	for _,part in pairs(PartsNearPlayer) do
		
		local Pickable = part.Parent:FindFirstChild("Pickable")
		local PickablePart = part.Parent:FindFirstChild("PickablePart")
		
		if PickablePart then 
		
			if Pickable.Value == true then
		
				local mag = (part.Parent:FindFirstChild("PickablePart").Position - plr.Character.HumanoidRootPart.Position).Magnitude
				table.insert(CloseInteractives, {Mag = mag, Part = part}) -- Put Part + Distance From Player in table
				
			end
		end
	end

	---- Sort Parts & Magnitudes ----
	
	if #CloseInteractives == 1 then -- If only 1 close part then continue
		
		return CloseInteractives[1].Part
		
	elseif #CloseInteractives > 1 then -- If multiple close parts get closest part
		
		table.sort(CloseInteractives, function(closest, other) 
			
			return closest.Mag < other.Mag
			
		end)
		
		return CloseInteractives[1].Part -- The first index in the table will be the closest part.
		
	else
		return nil
		
	end
	--------------------------------
	
end


--[[----------------------------------------
		  Interactive Module
-------------------------------------------]]--

runService.Heartbeat:Connect(function()
	
	---- Create Region3 Field ----
	
	local min = hrp.Position + radius * Vector3.new(-1,-1,-1)
	local max = hrp.Position + radius * Vector3.new(1,1,1)
	
	local region = Region3.new(min, max)
	
	local PartsNearPlayer = workspace:FindPartsInRegion3WithIgnoreList(region,{char}, 100)

	------------------------------
	
	---- Close Interactives Manager ----
	
	local ClosestInteractive = GetCloseInteractives(PartsNearPlayer)
	
	if ClosestInteractive ~= nil and ClosestInteractive ~= Interactive then -- If there is an interactive close enough and it isnt the current interactive.
		if Interactive == nil then -- If there is not an old interactive
			
			Interactive = ClosestInteractive
		else -- If there IS an old interactive	
		
			local PickablePart = Interactive.Parent:FindFirstChild("PickablePart")
			
			if PickablePart:FindFirstChild("ShowingInteractive") then
				
				PickablePart.ShowingInteractive:Destroy() -- Make the old interactive invisible.
				
			end
			
			Interactive = ClosestInteractive
		end
		
			local PickablePart = ClosestInteractive.Parent:FindFirstChild("PickablePart")
		
			local ShowImage = InteractiveImage:Clone()  -- Make the new interactive visible.
				ShowImage.Parent = PickablePart
				ShowImage.Enabled = true
				ShowImage.Name = "ShowingInteractive"
			
	elseif ClosestInteractive == nil then
		
		if Interactive ~= nil then 
			
			local PickablePart = Interactive.Parent:FindFirstChild("PickablePart")
			
			if PickablePart:FindFirstChild("ShowingInteractive") then
				
				PickablePart.ShowingInteractive:Destroy() -- Make the old interactive invisible.
				
			end
			
			Interactive = nil
		end
	end
	
	---- Binding Action ----

	if Interactive ~= nil then
		
		CAS:BindAction("Interact",ClickInteract,true, Enum.KeyCode.C)
		CAS:SetPosition("Interact", UDim2.new(1, -70, 0, 10))
			
	else
		
		CAS:UnbindAction("Interact")
		
	end
	
	-------------------------
end)

-----------------------------------------------

function ClickInteract(actionName, inputState)
	
	if inputState == Enum.UserInputState.Begin then
		
		Interactive.Parent.PickablePart.ShowingInteractive:Destroy()
		
		local InteractiveHub = require(storage.InteractiveHub)
		InteractiveHub.FindEventToFire(plr, Interactive.Parent)
		
	end
end

Don’t use loops, use an event. Look for an event in the documentation and use it.

Oh that actually worked thanks :smile: