How to detect where the player is touching the screen

I’ve posted about this on DevForum before, but I’m making a game where the player controls a plane. Currently I have both mouse/keyboard and Gamepad support, but I’d like to make the final leap to mobile support to ensure that all Roblox users have the opportunity to play my game.

However, I’m not at all familiar with scripting mobile controls, and I’m unsure as to what the proper method for detecting where the player is touching the screen is. This is my control code so far:

run.Stepped:Connect(function(_currentTime, deltaTime)
	if input.GamepadEnabled then
		av = Vector3.new(
			0,
			-(tstick.Position.X),
			(tstick.Position.Y)
		)
	elseif input.TouchEnabled then
		-- ??????
	else
		if input:IsMouseButtonPressed(1) then
			av = Vector3.new(
				0,
				((math.rad(-(mouse.X) + (mouse.ViewSizeX/2)))/2),
				((math.rad(-(mouse.Y) + (mouse.ViewSizeY/2)))/2)
			)
		else
			av = Vector3.new(
				0,
				0,
				0
			)
		end
	end

	plane.AngularVelocity.AngularVelocity = av
	plane.Orientation = Vector3.new(
		0,
		plane.Orientation.Y,
		plane.Orientation.Z
	)

	camera.CFrame = camera.CFrame:Lerp(plane.Attachment.WorldCFrame,8*deltaTime)
end)

Note how the code gets the mouse position and thumbstick position every frame, so I would simply need to grab the touch position in real time with no need to detect if the player is dragging their finger or not… or would I? Again the question is how I actually approach this in the first place.

Thanks in advance,
K3ology

2 Likes

Well, to add mobile touch controls to your game for controlling the plane, I believe you can use the UserInputService to detect touch input. The UserInputService provides information about input devices, including touch events on mobile devices.

Here’s an example of how you can modify your code to support touch controls:

local function getTouchPosition()
    local touches = game:GetService("UserInputService"):GetTouches()
    if #touches > 0 then
        -- Assume the player is using the first touch for control
        return touches[1].Position
    end
    return nil
end

run.Stepped:Connect(function(_currentTime, deltaTime)
    local av
    if input.GamepadEnabled then
        av = Vector3.new(
            0,
            -tstick.Position.X,
            tstick.Position.Y
        )
    elseif input.TouchEnabled then
        local touchPosition = getTouchPosition()
        if touchPosition then
            -- Convert the touch position to a normalized direction for control
            local halfWidth = workspace.CurrentCamera.ViewportSize.X / 2
            local halfHeight = workspace.CurrentCamera.ViewportSize.Y / 2
            local normalizedTouchPos = Vector2.new(
                (touchPosition.X - halfWidth) / halfWidth,
                (touchPosition.Y - halfHeight) / halfHeight
            )
            
            -- Use the normalizedTouchPos to control the plane (adjust the sensitivity as needed)
            av = Vector3.new(
                0,
                math.rad(-normalizedTouchPos.X) * sensitivityFactor,
                math.rad(-normalizedTouchPos.Y) * sensitivityFactor
            )
        else
            av = Vector3.new(0, 0, 0) -- No touch, no input
        end
    else
        -- Mouse/keyboard control as before
        -- ...
    end

    -- Rest of your code, K3ology
end)

In this code, I’ve added a new function getTouchPosition() to retrieve the position of the first touch on the screen. If a touch is detected, the position is then converted to a normalized direction vector, which is used to control the plane’s angular velocity. Adjust the sensitivityFactor variable to control how sensitive the touch controls should be. Remember that mobile devices come in various screen sizes, so it’s essential to handle different screen resolutions and aspect ratios appropriately to ensure the touch controls work consistently across devices. The code I provided above assumes a single touch control for simplicity, but you can extend it to support multiple touches if needed for your game.

1 Like

I added the code you suggested… the parts that worked, at least. GetTouches isn’t actually a valid method of UserInputService.

This is the entire script for clarity (I should’ve posted that before, oops), and while the code I added within the Stepped loop works, the script is unable to detect when the screen isn’t being touched anymore, and continues turning the plane after the fact.

Is there another function I can use to detect when the screen is being touched or not?

local run = game:GetService("RunService")
local input = game:GetService("UserInputService")
local mouse = game:GetService("Players").LocalPlayer:GetMouse()

local camera = workspace.CurrentCamera
local halfWidth = camera.ViewportSize.X / 2
local halfHeight = camera.ViewportSize.Y / 2
local sensitivityFactor = 100

local states = input:GetGamepadState(Enum.UserInputType.Gamepad1)
local statesByKeyCode = {}

for _, state in pairs(states) do
	statesByKeyCode[state.KeyCode] = state
end

local tstick = statesByKeyCode[Enum.KeyCode.Thumbstick2]

wait(1)

local plane = workspace:WaitForChild(script.Parent.Parent.Name .. "Plane")
local av = Vector3.new()

camera.CameraType = Enum.CameraType.Scriptable
camera.CameraSubject = plane
camera.FieldOfView = 45

run.Stepped:Connect(function(_currentTime, deltaTime)
	local av
	if input.GamepadEnabled then
		av = Vector3.new(
			0,
			-tstick.Position.X,
			tstick.Position.Y
		)
	elseif input.TouchEnabled then
		
		local touchPosition = input:GetMouseLocation()
		
		if touchPosition then
			local normalizedTouchPos = Vector2.new(
				(touchPosition.X - halfWidth) / halfWidth,
				(touchPosition.Y - halfHeight) / halfHeight
			)

			av = Vector3.new(
				0,
				math.rad(-normalizedTouchPos.X) * sensitivityFactor,
				math.rad(-normalizedTouchPos.Y) * sensitivityFactor
			)
		else
			av = Vector3.new(
				0,
				0,
				0)
		end
	else
		if input:IsMouseButtonPressed(1) then
			av = Vector3.new(
				0,
				((math.rad(-(mouse.X) + (mouse.ViewSizeX/2)))/2),
				((math.rad(-(mouse.Y) + (mouse.ViewSizeY/2)))/2)
			)
		else
			av = Vector3.new(
				0,
				0,
				0
			)
		end
	end

	plane.AngularVelocity.AngularVelocity = av
	plane.Orientation = Vector3.new(
		0,
		plane.Orientation.Y,
		plane.Orientation.Z
	)

	camera.CFrame = camera.CFrame:Lerp(plane.Attachment.WorldCFrame,8*deltaTime)
end)

I’m unable to record a video right now, but if you need more clarification, the mouse controls in the game itself provide a good example of the effect I’m looking for: 🎮Gamepad Support🎮 Plane Device Test - Roblox

I don’t know why but this seems AI generated…

4 Likes

Why not use UserInputService.TouchTap?
And here’s the documentation: UserInputService | Documentation - Roblox Creator Hub

Keep in mind, this can only be done in a local script. If you would like to get it on the server, you could pass the data it gives you via RemoteEvent


You can ask me for any extra help if you need it.

1 Like

Ended up figuring it out for myself after some more experimentation, here’s what I did for anyone who also has this issue:

	elseif input.TouchEnabled then
		local function onTouchMoved(touch, gameProcessedEvent)
			av = Vector3.new(
				0,
				((math.rad(-(touch.Position.X) + (mouse.ViewSizeX/2)))/2),
				((math.rad(-(touch.Position.Y) + (mouse.ViewSizeY/2)))/2)
			)
		end
		
		input.TouchMoved:Connect(onTouchMoved)
		
		local function onTouchEnded(touch, _gameProcessedEvent)
			av = Vector3.new(
				0,
				0,
				0
			)
		end
		
		input.TouchEnded:Connect(onTouchEnded)

Pretty self-explanatory tbh. Not sure if the gameProcessedEvent is needed as I just copied the variables from the documentation’s reference code but whatever idc

1 Like

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