How to adapt this to mobile?

I’m making a Placement System. I already made it for desktop, the problem is that I don’t know how to make it adapt to mobile. I’ve been thinking about using some already invented code and implementing it, but I don’t know if that would be the most efficient, can you help me??
Here is the .rblx:
BuildSystem.rbxl (83.5 KB)

And this is the main ModuleScript that control the Placement:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local boxOutlineTemplate = ReplicatedStorage.BoxOutline
local placeableObjects = ReplicatedStorage:WaitForChild("PlaceableObjects")
local tryPlace = ReplicatedStorage:WaitForChild("TryPlace")
local tryDelete = ReplicatedStorage:WaitForChild("TryDelete")
local UserInputService = game:GetService("UserInputService")
local ContextActionService = game:GetService("ContextActionService")
local RunService = game:GetService("RunService")
local camera = workspace.CurrentCamera
local PlacementValidator = require(ReplicatedStorage.PlacementValidator)

local PREVIEW_RENDER = "RenderPreview"
local ROTATE_ACTION = "Rotate"
local DELETE_ACTION = "Delete"
local SNAP_ACTION = "Snap"

-- Variable to store the last touch position
local lastTouchPosition = nil

-- Function to snap position to grid based on given size
local function snapToGrid(pos, gridSize)
	return Vector3.new(
		math.round(pos.X / gridSize) * gridSize,
		pos.Y,
		math.round(pos.Z / gridSize) * gridSize
	)
end

-- Function to cast a ray from a touch position on the screen and get the 3D position
local function castTouch(touchPosition)
	local rayOrigin = camera.CFrame.Position
	local rayDirection = (camera:ScreenPointToRay(touchPosition.X, touchPosition.Y)).Direction * 1000
	return workspace:Raycast(rayOrigin, rayDirection)
end

local ClientPlacer = {}
ClientPlacer.__index = ClientPlacer

function ClientPlacer.new(plot: Model, objectName: string)
	local self = setmetatable({
		Plot = plot,
		Preview = nil,
		GridSize = 0.5,
		Rotation = 0,
		SelectedObjectName = objectName,
	}, ClientPlacer)

	self:InitiateRenderPreview()
	-- Detect touches to place objects and store the position
	UserInputService.TouchTapInWorld:Connect(function(touchPosition)
		lastTouchPosition = touchPosition
		self:TryPlaceBlock(touchPosition)
	end)
	-- Rotate the object on double tap
	UserInputService.TouchTap:Connect(function(_, touchPositions)
		if #touchPositions == 2 then
			self:RotateBlock()
		end
	end)
	return self
end

-- Initializes the preview of the selected object for placement
function ClientPlacer:InitiateRenderPreview()
	local model = placeableObjects:FindFirstChild(self.SelectedObjectName)
	if model then
		self:PreparePreviewModel(model)
		RunService:BindToRenderStep(PREVIEW_RENDER, Enum.RenderPriority.Camera.Value, function() self:RenderPreview() end)
	else
		warn("Object not found in PlaceableObjects: " .. tostring(self.SelectedObjectName))
	end
end

-- Updates the preview model with a new selected object
function ClientPlacer:SetSelectedObject(newObjectName)
	self.SelectedObjectName = newObjectName

	local model = placeableObjects:FindFirstChild(newObjectName)
	if model then
		self:PreparePreviewModel(model)
	else
		warn("Selected object not found in PlaceableObjects: " .. tostring(newObjectName))
	end
end

-- Prepares the preview model with necessary settings
function ClientPlacer:PreparePreviewModel(model: Model)
	if self.Preview then 
		self.Preview:Destroy()
	end

	self.Preview = model:Clone()
	local boxOutline = boxOutlineTemplate:Clone()
	boxOutline.Adornee = self.Preview 
	boxOutline.Parent = self.Preview

	for _, part in self.Preview:GetDescendants() do
		if part:IsA("BasePart") then
			part.CanCollide = false
			part.CanQuery = false
			part.Transparency = 0.5
		end
	end

	self.Preview.Parent = workspace
end

-- Renders the placement preview at the touch position, snapping to grid if enabled
function ClientPlacer:RenderPreview()
	if lastTouchPosition then
		local cast = castTouch(lastTouchPosition)
		if cast and cast.Position then
			local position = if self.GridSize > 0 then snapToGrid(cast.Position, self.GridSize) else cast.Position
			local cf = CFrame.new(position) * CFrame.Angles(0, self.Rotation, 0)
			self.Preview:PivotTo(cf)

			local size = self.Preview:GetExtentsSize()
			self.Preview.BoxOutline.Color3 = 
				if PlacementValidator.WithinBounds(self.Plot, size, cf) 
				and PlacementValidator.NotIntersectingObjects(self.Plot, size, cf)
				then Color3.new(0, 0.666667, 1) 
				else Color3.new(1, 0, 0)
		end
	end
end

-- Attempts to place the preview object on the plot
function ClientPlacer:TryPlaceBlock(touchPosition)
	local cast = castTouch(touchPosition)
	if cast and cast.Position then
		local position = if self.GridSize > 0 then snapToGrid(cast.Position, self.GridSize) else cast.Position
		local cf = CFrame.new(position) * CFrame.Angles(0, self.Rotation, 0)

		-- Calls the server to place the object at the desired position
		local success = tryPlace:InvokeServer(self.Preview.Name, cf)
		if success then
			self:SetSelectedObject(self.SelectedObjectName)  -- Resets the preview for the next object
		else
			warn("Placement failed")
		end
	end
end

-- Rotates the preview object 90 degrees
function ClientPlacer:RotateBlock()
	self.Rotation += math.pi / 2 -- 90 degrees
end

-- Cleans up and disables actions when placement mode is deactivated
function ClientPlacer:Destroy()
	if self.Preview then 
		self.Preview:Destroy()
	end
	RunService:UnbindFromRenderStep(PREVIEW_RENDER)
end

return ClientPlacer