How do i make UI on Mobile ignore the new inputs from new tap

Currently my game has this method of swiping a mobile buttons while also moving a camera, This was a temporary solution to make firebutton easier to use and alternative to most inputs since roblox doesn’t offer a thumbstick or a way to make multi-touch, here most of the game i believe becomes even painful to move so while a player is holding the buttons for example and user moves the touch position out of the bound, function still runs even if you released the finger after swiped outside

ContextActionService/UserInputService when used in most games

as you can see, a fire function ends if they’re inside a button player was holding so i came up with a way of using RunService updating along with mouse location (since TouchStarted don’t exist on buttons GUI) so the only way was to use a GetMouseLocation() from UserInputService and there’s a problem again.

on Emulator

method worked out pretty fine on single touch but soon as player moves while reaching to another button, it flickers to another new input rather than staying on old ones sometimes which looked like this on phone

On actual phone

here’s also the script

local inputSV = game:GetService("UserInputService")
local runSV = game:GetService("RunService")

local gui = script.Parent
local butonz_pak = gui.butonz
local mouse_evt = nil
local mouse_process

local inputted = false
local touch_crv

butonz_pak.FireButton.InputBegan:Connect(function(inputOBJ, game_evt_proc)
	inputted = true --boolean sorted out wrong but i'll change the way later
	if inputOBJ.UserInputType == Enum.UserInputType.Touch or inputOBJ.UserInputType == Enum.UserInputType.MouseButton1 and inputOBJ.UserInputState == Enum.UserInputState.Begin then --mouse check exists for debugging purposes
		if inputted then
			for ind, butonz in pairs(butonz_pak:GetChildren()) do --hide all action buttons, preventing unexpected inputs
				if butonz.Name ~= "FireButton" then
					butonz.Visible = false
				end
			end

			mouse_process = runSV.RenderStepped:Connect(function(delta) --connect while holding buttons
				mouse_evt = inputSV:GetMouseLocation() --no such TouchStarted exists so this was used
				butonz_pak.FireButton.Position = UDim2.fromOffset(mouse_evt.X, mouse_evt.Y - 30)
				butonz_pak.FireButton.Size = UDim2.fromScale(0.172, 0.301)
			end)
		end
	end
end)

butonz_pak.FireButton.InputEnded:Connect(function(inputOBJ, game_evt_proc)
	inputted = false --boolean sorted out wrong but i'll change the way later
	
	if inputOBJ.UserInputType == Enum.UserInputType.Touch or inputOBJ.UserInputType == Enum.UserInputType.MouseButton1 and inputOBJ.UserInputState ~= Enum.UserInputState.Begin then --mouse check exists for debugging purposes
		if not inputted then
			mouse_process:Disconnect()
			mouse_evt = nil
			butonz_pak.FireButton.Position = UDim2.fromScale(0.797, 0.665)
			butonz_pak.FireButton.Size = UDim2.fromScale(0.094, 0.164)

			for ind, butonz in pairs(butonz_pak:GetChildren()) do
				butonz.Visible = true
			end
		end
	end	
end)

Turns out the InputObject gets created and UI follows by the mouse location, i had to reference the first touch from the InputObject and get a rid of GetMouseLocation() since that does not support multi touch and is meant for mouse (most games utilizes on mouse only on mobile supported games) This worked out pretty well

local runSV = game:GetService("RunService")

local gui = script.Parent
local butonz_pak = gui.butonz --folders
local mouse_process

local inputted = false
local touch_crv

butonz_pak.FireButton.InputBegan:Connect(function(inputOBJ, game_evt_proc)
	if not (touch_crv) or (touch_crv == inputOBJ) then 
		touch_crv = inputOBJ --if first touch is pressed then assign it to touch_crv
		if touch_crv.UserInputType == Enum.UserInputType.Touch and touch_crv.UserInputState == Enum.UserInputState.Begin and not inputted then
			inputted = true 
			for ind, butonz in pairs(butonz_pak:GetChildren()) do --hide all action buttons, preventing unexpected inputs
				if butonz.Name ~= "FireButton" then
					butonz.Visible = false
				end
			end

			mouse_process = runSV.RenderStepped:Connect(function(delta) --Because touch events for UI don't work on first tap, we have to use RunService 
				butonz_pak.FireButton.Position = UDim2.fromOffset(touch_crv.Position.X, touch_crv.Position.Y) --InputObject by default uses vector3 but you can use X and Y only
				butonz_pak.FireButton.Size = UDim2.fromScale(0.172, 0.301) --scale image
			end)
		end
	else --else meaning that it's for other touch, preventing flickers
		if inputOBJ.UserInputType == Enum.UserInputType.Touch and inputOBJ.UserInputState == Enum.UserInputState.Begin and not inputted then
			inputted = true --boolean sorted out wrong but i'll change the way later
			for ind, butonz in pairs(butonz_pak:GetChildren()) do --hide all action buttons, preventing unexpected inputs
				if butonz.Name ~= "FireButton" then
					butonz.Visible = false
				end
			end

			mouse_process = runSV.RenderStepped:Connect(function(delta) --connect while holding buttons
				butonz_pak.FireButton.Position = UDim2.fromOffset(touch_crv.Position.X, touch_crv.Position.Y) --InputObject by default uses vector3 but you can use X and Y only
				butonz_pak.FireButton.Size = UDim2.fromScale(0.172, 0.301)
			end)
		end
	end
end)

butonz_pak.FireButton.InputEnded:Connect(function(inputOBJ, game_evt_proc)
	inputted = false --boolean sorted out wrong but i'll change the way later
	if touch_crv == inputOBJ then --if first touch is still inputobject (either first or second)
		touch_crv = nil --then we set it to nil
		mouse_process:Disconnect() --RunService still runs when we assign it so this is required to do
		butonz_pak.FireButton.Position = UDim2.fromScale(0.797, 0.665)
		butonz_pak.FireButton.Size = UDim2.fromScale(0.094, 0.164)
		
		for ind, butonz in pairs(butonz_pak:GetChildren()) do --make all buttons in butonz_pak visible
			butonz.Visible = true
		end
		
	else --same applies to below
		inputted = false --boolean sorted out wrong but i'll change the way later
		mouse_process:Disconnect()
		touch_crv = nil
		butonz_pak.FireButton.Position = UDim2.fromScale(0.797, 0.665)
		butonz_pak.FireButton.Size = UDim2.fromScale(0.094, 0.164)

		for ind, butonz in pairs(butonz_pak:GetChildren()) do
			butonz.Visible = true
		end
	end
end)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.