Dragging script not working correctly on tablets/mobiles

For some reason objects are too heavy, the movement joystick is not showing either.

The user should be able to drag the part and move around with it.

here is my script:


-- Dependencies:
local replicatedStorage = game:GetService("ReplicatedStorage")
local contextActionService = game:GetService("ContextActionService")
local runService = game:GetService("RunService")
local players = game:GetService("Players")
local userInputService = game:GetService("UserInputService")
local clientModules = replicatedStorage.Modules.Client
local dragController = require(clientModules.DragController)
local inputTypeDetector = require(clientModules.InputTypeDetector)
local localPlayer = players.LocalPlayer
local control
local baseCamera
coroutine.wrap(function()
	local playerModule = localPlayer.PlayerScripts:WaitForChild("PlayerModule")
	control = require(playerModule):GetControls()
	baseCamera = require(playerModule:WaitForChild("CameraModule"):WaitForChild("BaseCamera"))
end)()

-- Paths:
local network = replicatedStorage.Network
local requestDrag = network.RequestDrag
local dragCancelled = network.DragCancelled

-- Data:
local inputTypes = inputTypeDetector.InputTypes
local target
local hit

-- Configuration:
local MAX_GRAB_DISTANCE = 10

-- Main:
contextActionService:BindAction("Drag", function(name, state, input)
	if state == Enum.UserInputState.Begin then
		if dragController.IsDragging then return Enum.ContextActionResult.Pass end
		-- Get head
		local character = localPlayer.Character
		if character == nil then return Enum.ContextActionResult.Pass end
		local head = character:FindFirstChild("Head")
		if head == nil then return Enum.ContextActionResult.Pass end
		-- Get target
		local inputType = inputTypeDetector.GetInputType()
		if inputType == inputTypes.KeyboardAndMouse or inputType == inputTypes.Gamepad then
			if target == nil or hit == nil then return Enum.ContextActionResult.Pass end
		elseif inputType == inputTypes.Touch then
			if input.UserInputType ~= Enum.UserInputType.Touch then return Enum.ContextActionResult.Pass end
			local inputPosition = input.Position
			local screenPointRay = workspace.CurrentCamera:ScreenPointToRay(inputPosition.X, inputPosition.Y)
			local extendedRay = Ray.new(screenPointRay.Origin, screenPointRay.Direction * 1000)
			target, hit = workspace:FindPartOnRay(extendedRay, localPlayer.Character, false, true)
		end
		-- Check if can drag
		if not dragController.CanDrag(target) then return Enum.ContextActionResult.Pass end
		if (head.Position - hit).Magnitude > MAX_GRAB_DISTANCE then return Enum.ContextActionResult.Pass end
		-- Prepare if touch
		if inputType == inputTypes.Touch then
			control:Disable()
		end
		-- Drag
		dragController.Drag(target, hit)
		-- Register drag on server
		local wasCancelled = false
		local connection
		connection = dragController.DragCancelled:Connect(function()
			connection:Disconnect()
			wasCancelled = true
			if inputType ~= inputTypes.Touch then return end
			control:Enable()
		end)
		local isSuccessful = requestDrag:InvokeServer(target)
		if wasCancelled or isSuccessful then return end
		dragController.CancelDrag()
	else
		if state == Enum.UserInputState.End then
			dragController.CancelDrag()
		end
		return Enum.ContextActionResult.Pass
	end
end, false, Enum.UserInputType.MouseButton1, Enum.UserInputType.Touch, Enum.KeyCode.ButtonR2)

while true do
	local inputType = inputTypeDetector.GetInputType()
	if inputType == inputTypes.KeyboardAndMouse or inputType == inputTypes.Gamepad then
		local location = userInputService:GetMouseLocation()
		local viewportPointRay = workspace.CurrentCamera:ViewportPointToRay(location.X, location.Y)
		local extendedRay = Ray.new(viewportPointRay.Origin, viewportPointRay.Direction * 1000)
		target, hit = workspace:FindPartOnRay(extendedRay, localPlayer.Character, false, true)
	end
	runService.Heartbeat:Wait()
end

next script

-- ServerScriptService > Scripts > Draghandler
--draghandler
-- dependencies:
local replicatedStorage = game:GetService("ReplicatedStorage")
local serverScriptService = game:GetService("ServerScriptService")
local dragController = require(serverScriptService.Modules.DragController)

-- paths:
local network = replicatedStorage.Network
local requestDrag = network.RequestDrag
local dragCancelled = network.DragCancelled


-- main:
function requestDrag.OnServerInvoke(player, part)
	if not dragController.CanDrag(player, part) then return false end
	dragController.Drag(player, part)
	
	return true
end

dragCancelled.OnServerEvent:Connect(function(player)
	-- TODO
end)

next

-- ServerScriptService > Modules (folder) > DragController (module script)
--dragcontroller script
-- dependencies:
local players = game:GetService("Players")
local collectionService = game:GetService("CollectionService")

-- data:
local playerToDragData = {}


-- DragController:
local module = {}

function module.Drag(player, part)
	assert(typeof(player) == "Instance" and player:IsA("Player"), "bad argument #1 to DragController.Drag, expects Instance<Player>")
	assert(module.CanDrag(player, part), "bad argument #2 to DragController.Drag, expects part that can be dragged")

	part:SetNetworkOwner(player)
end

function module.CanDrag(player, part)
	assert(typeof(player) == "Instance" and player:IsA("Player"), "bad argument #1 to DragController.CanDrag, expects Instance<Player>")

	if module.IsDragging(player) then return false end
	if typeof(part) ~= "Instance" then return false end
	if not part:FindFirstChild("Configuration") then return false end  -- Check if part has a Configuration child
	local owner = part.Owner.Value
	if owner ~= 0 and owner ~= player.UserId then return false end -- TODO: add player whitelist checks

	return true
end

function module.IsDragging(player)
	assert(typeof(player) == "Instance" and player:IsA("Player"), "bad argument #1 to DragController.IsDragging, expects Instance<Player>")
	
	local dragData = playerToDragData[player]
	if dragData == nil then return end
	
	return dragData.IsDragging
end


-- main:
players.PlayerAdded:Connect(function(player)
	playerToDragData[player] = {
		IsDragging = false,
	}
end)

players.PlayerRemoving:Connect(function(player)
	playerToDragData[player] = nil
end)


return module

next

--ReplicatedStorage > Modules > Client > InputTypeDetector
-- dependencies:
local userInputService = game:GetService("UserInputService")

-- enums
local inputTypes = {
	KeyboardAndMouse = 1,
	Gamepad = 2,
	Touch = 3,
}

-- data:
local inputTypeToEnumMap = {
	[Enum.UserInputType.MouseButton1] = inputTypes.KeyboardAndMouse,
	[Enum.UserInputType.MouseButton2] = inputTypes.KeyboardAndMouse,
	[Enum.UserInputType.MouseButton3] = inputTypes.KeyboardAndMouse,
	[Enum.UserInputType.MouseWheel] = inputTypes.KeyboardAndMouse,
	[Enum.UserInputType.MouseMovement] = inputTypes.KeyboardAndMouse,
	[Enum.UserInputType.Keyboard] = inputTypes.KeyboardAndMouse,
	[Enum.UserInputType.Touch] = inputTypes.Touch,
	[Enum.UserInputType.Gamepad1] = inputTypes.Gamepad,
	[Enum.UserInputType.Gamepad2] = inputTypes.Gamepad,
	[Enum.UserInputType.Gamepad3] = inputTypes.Gamepad,
	[Enum.UserInputType.Gamepad4] = inputTypes.Gamepad,
	[Enum.UserInputType.Gamepad5] = inputTypes.Gamepad,
	[Enum.UserInputType.Gamepad6] = inputTypes.Gamepad,
	[Enum.UserInputType.Gamepad7] = inputTypes.Gamepad,
	[Enum.UserInputType.Gamepad8] = inputTypes.Gamepad,
}
local inputType = inputTypeToEnumMap[userInputService:GetLastInputType()] or inputTypes.KeyboardAndMouse
local inputTypeChangedBindable = Instance.new("BindableEvent")


-- ClientUtil:
local module = {}

function module.GetInputType()
	return inputType
end


module.InputTypeChanged = inputTypeChangedBindable.Event

module.InputTypes = inputTypes


-- main:
userInputService.LastInputTypeChanged:Connect(function(newInputType)
	local enum = inputTypeToEnumMap[newInputType]
	if enum == nil then return end
	if enum == inputType then return end
	inputType = enum
	inputTypeChangedBindable:Fire(inputType)
end)

return module

next

--Replicatedstorage > Modules > client > Dragcontroller
-- dependencies:
local runService = game:GetService("RunService")
local collectionService = game:GetService("CollectionService")
local userInputService = game:GetService("UserInputService")
local players = game:GetService("Players")
local localPlayer = players.LocalPlayer
local playerScripts = localPlayer.PlayerScripts
local baseCamera
coroutine.wrap(function()
	baseCamera = require(playerScripts:WaitForChild("PlayerModule"):WaitForChild("CameraModule"):WaitForChild("BaseCamera"))
end)()

-- paths:
local holdTarget = script.HoldTarget
local holdPositionAlignment = script.HoldPositionAlignment
local logic = workspace.Logic

-- data:
local holdGrip = Instance.new("Attachment")
local dragCancelledBindable = Instance.new("BindableEvent")
local draggedBindable = Instance.new("BindableEvent")
local currentHoldGrip
local heldPart

-- configuration:
local DRAG_DISTANCE = 10


-- DragController:
local module = {}

function module.CancelDrag()
	if not module.IsDragging then return end
	currentHoldGrip:Destroy()
	currentHoldGrip = nil
	holdPositionAlignment.Attachment0 = nil
	heldPart = nil
	module.IsDragging = false
	dragCancelledBindable:Fire()
end

function module.Drag(part, position)
	assert(module.CanDrag(part), "bad argument #1 to DragController.Drag, expects part that can be dragged")
	assert(typeof(position) == "Vector3" or position == nil, "bad argument #2 to DragController.Drag, expects Vector3?")
	
	if position == nil then
		position = Vector3.new()
	end
	local cFrame = CFrame.new(position)
	module.IsDragging = true
	heldPart = part
	currentHoldGrip = holdGrip:Clone()
	currentHoldGrip.Position = part.CFrame:ToObjectSpace(cFrame).Position
	currentHoldGrip.Parent = heldPart
	holdPositionAlignment.Attachment0 = currentHoldGrip
	holdTarget.CFrame = cFrame
	draggedBindable:Fire(part, position)
end

function module.CanDrag(part)
	if module.IsDragging then return false end
	if typeof(part) ~= "Instance" then return false end
	if not collectionService:HasTag(part, "Draggable") then return false end
	local owner = part.Owner.Value
	if owner ~= 0 and owner ~= localPlayer.UserId then return false end -- TODO: add player whitelist checks
	
	return true
end

module.IsDragging = false

module.Dragged = draggedBindable.Event

module.DragCancelled = dragCancelledBindable.Event


-- main:
holdGrip.Visible = true
holdPositionAlignment.Parent = logic
holdTarget.Parent = logic

local function merge(a1, a2)
	for _, v2 in ipairs(a2) do
		table.insert(a1, v2)
	end
	
	return a1
end

coroutine.wrap(function()
	while true do
		if module.IsDragging and baseCamera ~= nil then
			-- get necessary data
			local subjectPosition = baseCamera:GetSubjectPosition()
			if subjectPosition == nil then return end
			-- get hit
			local location = userInputService:GetMouseLocation()
			local viewportPointRay = workspace.CurrentCamera:ViewportPointToRay(location.X, location.Y)
			local rayOrigin = viewportPointRay.Origin
			local mousePosition = CFrame.new(rayOrigin, rayOrigin + viewportPointRay.Direction):ToWorldSpace(CFrame.new(0, 0, -1000)).Position
			local targetPosition = CFrame.new(subjectPosition, mousePosition):ToWorldSpace(CFrame.new(0, 0, -DRAG_DISTANCE)).Position
			holdTarget.CFrame = CFrame.new(targetPosition)
		end
		runService.Heartbeat:Wait()
	end
end)()

return module

Can someone help with this please. I cannot figure it out.