How to stop camera model from moving with camera pan on mobile?

I am really far over my knowledge of CFrames and ray casts here so I am going to try to explain it best as possible. The pc version works fine however the mobile one is a bit tempermental and I cant get it to not move when the player rotates their camera.

Here is the mobile function, I am considering run service over a while loop. Anyway I need to make it like lumber tycoons mobile placement. Here are some videos:

Issue with camera movement

Lumber tycoon reference:

I am really stuck and any help will be greatly appreciated.

Our mobile code function:

local function MobileGrab()
	local PlayerGUI = player.PlayerGui
	local Mouse = player:GetMouse() -- // This works on mobile

	local Magnitude = (mouse.Hit.Position - character.Head.CFrame.Position).magnitude

	local Button = PlayerGUI.PlaceGUI.Drop
	Button.MouseButton1Down:Connect(function()
		PlayerGUI.PlaceGUI.Enabled = false
		GrabModel.PrimaryPart.LocalPizzaPrompt.Enabled = true
		GrabObject = nil
		GrabStart = false
		if Dragger then
			Dragger:Destroy()
			Dragger = nil
		end
	end)

	if Magnitude < 10 then

		if mouse.Target then

			GrabObject = mouse.Target
			GrabStart = true

			if GrabObject.Name == "Pizza" or GrabObject.Parent.Name == "Pizza" then
				--print("OBJ")
				--for i, v in pairs(GrabObject.Parent:GetChildren()) do
				--	v.CanCollide = false
				--end
			end					

			local DragBall = createDragBall()
			DragBall.CFrame = mouse.Hit
			Dragger = DragBall

			mouse.TargetFilter = GrabObject

			local DragBallWeld = weldBetween(DragBall,GrabObject)
			addMover(DragBall)

			local cf = CFrame.new(character.Head.Position, mouse.Hit.Position)
			Dragger.Mover.Position = ((cf + (cf.LookVector * 6)).Position + Vector3.new(0, 2, 0))
			Dragger.RotMover.CFrame = camera.CFrame * CFrame.Angles(Dragger.RotOffset.Value.X,Dragger.RotOffset.Value.Y + 2, Dragger.RotOffset.Value.Z)

			while Dragger do
				--Create a ray from the users head to the mouse.
				if not UserInputService.TouchPan and UserInputService.TouchTap or UserInputService.TouchLongPress then
					local cf = CFrame.new(character.Head.Position, mouse.Hit.Position)
					Dragger.Mover.Position = (cf + (cf.LookVector * 6)).Position
					Dragger.RotMover.CFrame = camera.CFrame * CFrame.Angles(Dragger.RotOffset.Value.X,Dragger.RotOffset.Value.Y, Dragger.RotOffset.Value.Z)
				end				
				task.wait(0.08)
			end
			mouse.TargetFilter = nil
		end
	end	
end

Any help is appreciated I have looked extensively through the new and old documentation on ray casts, mouse and touch user input and I still remain highly stuck.

do you somehow know about the lookvector in cframe?

if yes then you can use that to position the pizza, if not then ill try my best to explain it to you

No I dont, I have little understanding of CFrames.

ight ight, ill try to make something like that.

ill get back to you as soon as i can

1 Like

So im making it from scratch and having a hard time lol, ill continue it after i take some night rest

local userInputServ = game:GetService("UserInputService")
local runServ = game:GetService("RunService")

local player
if game.Players.LocalPlayer then
	player = game.Players.LocalPlayer
else
	task.wait()
	player = game.Players.LocalPlayer
end

local character = player.Character or player.CharacterAdded:Wait()

local camera = workspace.CurrentCamera

local isHolding = false

local targetObj = nil

function grabObject()
	task.wait()
	
	if targetObj ~= nil then
		if isHolding then
			local mouse = player:GetMouse()
			
			local magnitude = (mouse.Hit.Position - character.HumanoidRootPart.CFrame.Position).magnitude
			
			mouse.TargetFilter = player.Character
			
			if magnitude < 20 then
				if targetObj:IsA("BasePart") and targetObj:FindFirstChild("CanGrab") then
					if targetObj.CanCollide then
						--targetObj.CanCollide = false
					end

					print(magnitude)

					--targetObj.CFrame = CFrame.new(Vector3.new(math.clamp(character.HumanoidRootPart.Position.X - mouse.Hit.Position.X, 0, 20)))

					--targetObj.CFrame = CFrame.new(character.HumanoidRootPart.CFrame.Position + character.HumanoidRootPart.CFrame.LookVector * 10)

					targetObj.CFrame = CFrame.new(Vector3.new(math.clamp(mouse.Hit.Position.X, character.HumanoidRootPart.Position.X - 20, character.HumanoidRootPart.Position.X + 20), math.clamp(mouse.Hit.Position.Y, character.HumanoidRootPart.Position.Y - 5, character.HumanoidRootPart.Position.Y + 20), math.clamp(mouse.Hit.Position.Z, character.HumanoidRootPart.Position.Z - 20, character.HumanoidRootPart.Position.Z + 20)))

				end
			end
		end
	end
end

userInputServ.InputBegan:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		isHolding = true
		
		local mouse = player:GetMouse()
		mouse.TargetFilter = player.Character

		
		local target = mouse.Target
	
		if target then
			if target:IsA("BasePart") then
				targetObj = target
				
			end
		end
	end
end)

userInputServ.InputEnded:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		isHolding = false
		
		targetObj.CanCollide = true
		
		targetObj = nil
	end
end)

runServ:BindToRenderStep("MovePart", Enum.RenderPriority.Camera.Value, grabObject)


Thank you so much! I will let you know if it helped

and im back,
ive made it, im not sure tho if its how you want it to be

but it works like the one in lumber tycoon (not exactly, but you can easily modify it by using tweens or lerp or whatever)

here’s the clip of it:

imma just clean up the script (local) then imma post it here

and here, still im not sure if this is how you want it to be like

i tried my best

Create a part and add anything inside named “CanGrab” to make a part draggable

local userInputServ = game:GetService("UserInputService")
local runServ = game:GetService("RunService")

local player
if game.Players.LocalPlayer then
	player = game.Players.LocalPlayer
else
	task.wait()
	player = game.Players.LocalPlayer
end

local camera = workspace.CurrentCamera

local isHolding = false

local targetObj = nil

local rayTable = {player.Character}

local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.FilterDescendantsInstances = rayTable
raycastParams.IgnoreWater = true

local faceCharacter = false -- face the character when getting dragged- //NOT RECOMMENDED//
local makePartNonCollidable = true -- Make Part non-collidable when getting dragged đź’€

function grabObject()
	task.wait()
	
	if targetObj ~= nil then
		if isHolding then
			if not table.find(rayTable, targetObj) then
				table.insert(rayTable, targetObj)
			end
			
			local character = player.Character
			local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
			
			local mouseLocation = userInputServ:GetMouseLocation()
			local viewportPointRay = camera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
			
			raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
			raycastParams.FilterDescendantsInstances = rayTable
			
			local target = workspace:Raycast(viewportPointRay.Origin, viewportPointRay.Direction * 1000, raycastParams) or {Position = (viewportPointRay.Origin + viewportPointRay.Direction * 1000)}

			local magnitude = (target.Position - humanoidRootPart.CFrame.Position).magnitude
			
			local newCFrame
			if faceCharacter then
				newCFrame = CFrame.new(Vector3.new(target.Position.X, target.Position.Y + 2, target.Position.Z), humanoidRootPart.Position)
			else
				newCFrame = CFrame.new(Vector3.new(target.Position.X, target.Position.Y + 2, target.Position.Z))
			end
			
			if (humanoidRootPart.CFrame.Position - newCFrame.Position).Magnitude < 20 then
				if targetObj:IsA("BasePart") and targetObj:FindFirstChild("CanGrab") then
					if targetObj.CanCollide and makePartNonCollidable then
						targetObj.CanCollide = false
					end
					
					targetObj.CFrame = newCFrame
				end
			else				
				local direction = (target.Position - humanoidRootPart.Position).Unit

				local newPosition = Vector3.new(20, 20, 20) * direction
				
				if faceCharacter then
					targetObj.CFrame = CFrame.new(Vector3.new(humanoidRootPart.Position.X + newPosition.X, (humanoidRootPart.Position.Y + newPosition.Y) + 2, humanoidRootPart.Position.Z + newPosition.Z), humanoidRootPart.Position)	
				else
					targetObj.CFrame = CFrame.new(Vector3.new(humanoidRootPart.Position.X + newPosition.X, (humanoidRootPart.Position.Y + newPosition.Y) + 2, humanoidRootPart.Position.Z + newPosition.Z))	
				end
			end
		end
	end
end

userInputServ.InputBegan:Connect(function(input, processed)
	if not userInputServ.TouchEnabled then
		if not processed then
			if input.UserInputType == Enum.UserInputType.MouseButton1 then
				isHolding = true

				local mouseLocation = userInputServ:GetMouseLocation()
				local viewportPointRay = camera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
				local extendedRay = Ray.new(viewportPointRay.Origin, viewportPointRay.Direction * 1000)

				local target = workspace:Raycast(viewportPointRay.Origin, viewportPointRay.Direction * 1000, raycastParams)

				if target then
					local targetInstance = target.Instance

					if targetInstance:IsA("BasePart") then
						if targetInstance:FindFirstChild("CanGrab") then
							targetObj = targetInstance

							table.insert(rayTable, targetObj)

							raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
							raycastParams.FilterDescendantsInstances = rayTable
							raycastParams.IgnoreWater = true
						end				
					end
				end
			end
		end
	else
		if not processed then
			if input.UserInputType == Enum.UserInputType.Touch then
				isHolding = true

				local mouseLocation = userInputServ:GetMouseLocation()
				local viewportPointRay = camera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
				local extendedRay = Ray.new(viewportPointRay.Origin, viewportPointRay.Direction * 1000)

				local target = workspace:Raycast(viewportPointRay.Origin, viewportPointRay.Direction * 1000, raycastParams)

				if target then
					local targetInstance = target.Instance

					if targetInstance:IsA("BasePart") then
						if targetInstance:FindFirstChild("CanGrab") then						
							targetObj = targetInstance

							table.insert(rayTable, targetObj)

							raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
							raycastParams.FilterDescendantsInstances = rayTable
						end				
					end
				end
			end
		end
	end
end)

userInputServ.InputEnded:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
		isHolding = false
		
		if targetObj ~= nil then		
			targetObj.CanCollide = true -- Just in case you made it non-collidable
		end
		
		for i, v in pairs(rayTable) do
			if v == targetObj then
				table.remove(rayTable, i)
			end
		end
		
		targetObj = nil
		
		raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
		raycastParams.FilterDescendantsInstances = rayTable
	end
end)

runServ:BindToRenderStep("MovePart", Enum.RenderPriority.Camera.Value, grabObject)

Its broken again. I tried your code and it wouldn’t work on mobile or pc. Here’s my current code:

local ServicesModule = require(script.Parent.Parent.ServicesModule)
local CAS = ServicesModule["ContextActionService"]
local UserInputService = ServicesModule["UserInputService"]
local PhysicsService = ServicesModule["PhysicsService"]
local ReplicatedStorage = ServicesModule["ReplicatedStorage"]

local PizzaFollowModule = {}

local GrabObject = nil
local GrabStart = false
local Dragger = nil
local GrabModel = workspace.Pizza

local player = ServicesModule["Players"].LocalPlayer
local character = player.Character
local mouse = player:GetMouse()
local camera = game.Workspace.CurrentCamera

-- // Ray table:
local rayTable = {player.Character}

-- // Raycast:
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.FilterDescendantsInstances = rayTable
raycastParams.IgnoreWater = true

local faceCharacter = false -- // face the character when getting dragged

-- // Welding function:
local function weldBetween(a, b)
	local weld = Instance.new("ManualWeld", a)
	weld.C0 = a.CFrame:inverse() * b.CFrame
	weld.Part0 = a
	weld.Part1 = b
	return weld
end

-- // Collision Function:
local previousCollisionGroups = {}

local function setCollisionGroup(object)
	if object:IsA("BasePart") then
		previousCollisionGroups[object] = object.CollisionGroupId
		PhysicsService:SetPartCollisionGroup(object, "Player Local")
	end
end

local function setCollisionGroupRecursive(object)
	setCollisionGroup(object)

	for _, child in ipairs(object:GetChildren()) do
		setCollisionGroupRecursive(child)
	end
end

local function resetCollisionGroup(object)
	local previousCollisionGroupId = previousCollisionGroups[object]
	if not previousCollisionGroupId then return end 

	local previousCollisionGroupName = PhysicsService:GetCollisionGroupName(previousCollisionGroupId)
	if not previousCollisionGroupName then return end

	PhysicsService:SetPartCollisionGroup(object, previousCollisionGroupName)
	previousCollisionGroups[object] = nil
end

local function onCharacterAdded(character)
	setCollisionGroupRecursive(character)

	character.DescendantAdded:Connect(setCollisionGroup)
	character.DescendantRemoving:Connect(resetCollisionGroup)
end

-- // Pizza Collision:
local function SetPizzaCollision(Model)
	for i, v in pairs(Model:GetChildren()) do
		if v:IsA("BasePart") then
			PhysicsService:SetPartCollisionGroup(v, "Pizza Local")
		end
	end
end

-- // Creating the mover:
function addMover(part)
	local newMover = Instance.new("BodyPosition")
	newMover.Parent = part
	newMover.MaxForce = Vector3.new(40000,40000,40000)
	newMover.P = 15000
	newMover.D = 1000
	newMover.Position = part.Position
	newMover.Name = "Mover"

	local newRot = Instance.new("BodyGyro")
	newRot.Parent = part
	newRot.MaxTorque = Vector3.new(3000,3000,3000)
	newRot.P = 3000
	newRot.D = 500
	newRot.CFrame = game.Workspace.CurrentCamera.CFrame
	newRot.Name = "RotMover"

	local RotOffset = Instance.new("CFrameValue")
	RotOffset.Name = "RotOffset"
	RotOffset.Parent = part
end

-- // Creating the dragable object
function createDragBall()
	local DragBall = Instance.new("Part")
	-- // DragBall.BrickColor = BrickColor.new("Electric blue")
	-- // DragBall.Material = Enum.Material.Wood
	DragBall.Transparency = 1
	DragBall.Size = Vector3.new(.2,.2,.2)
	DragBall.Shape = "Ball"
	DragBall.Name = "DragBall"
	DragBall.Parent = workspace
	return DragBall
end

function grabObject()
	task.wait()

	if Dragger ~= nil then
		if not table.find(rayTable, Dragger) then
			table.insert(rayTable, Dragger)
		end
		
		local character = player.Character
		local humanoidRootPart = character:WaitForChild("HumanoidRootPart")

		local mouseLocation = UserInputService:GetMouseLocation()
		local viewportPointRay = camera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
		
		raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
		raycastParams.FilterDescendantsInstances = rayTable

		local target = workspace:Raycast(viewportPointRay.Origin, viewportPointRay.Direction * 100, raycastParams) or {Position = (viewportPointRay.Origin + viewportPointRay.Direction * 1000)}

		local magnitude = (target.Position - humanoidRootPart.CFrame.Position).magnitude

		local newCFrame
		if faceCharacter then
			newCFrame = CFrame.new(Vector3.new(target.Position.X, target.Position.Y + 0, target.Position.Z), humanoidRootPart.Position)
		else
			newCFrame = CFrame.new(Vector3.new(target.Position.X, target.Position.Y + 0, target.Position.Z))
		end

		if (humanoidRootPart.CFrame.Position - newCFrame.Position).Magnitude < 10 then
			if Dragger:IsA("BasePart") then
				Dragger.CFrame = newCFrame
			end
		else				
			local direction = (target.Position - humanoidRootPart.Position).Unit
			
			local newPosition = Vector3.new(0.1, 0.1, 0.1) * direction
			
			if faceCharacter then
				Dragger.CFrame = CFrame.new(Vector3.new(humanoidRootPart.Position.X + newPosition.X, (humanoidRootPart.Position.Y + newPosition.Y) + 2, humanoidRootPart.Position.Z + newPosition.Z), humanoidRootPart.Position)	
			else
				Dragger.CFrame = CFrame.new(Vector3.new(humanoidRootPart.Position.X + newPosition.X, (humanoidRootPart.Position.Y + newPosition.Y) + 2, humanoidRootPart.Position.Z + newPosition.Z))	
			end
		end
		
	end
end

-- // Grab function:
function Grab(actionName, UserInputState, InputObject)
	if actionName == "Grab" then
		if UserInputState == Enum.UserInputState.Begin then
			-- start grab
			local Magnitude = (mouse.Hit.Position - character.Head.CFrame.Position).magnitude
			if Magnitude < 10 then

				if mouse.Target then

					GrabObject = mouse.Target
					GrabStart = true

					if GrabObject.Name == "Pizza" or GrabObject.Parent.Name == "Pizza" then
						print("OBJ")
						--	for i, v in pairs(GrabObject.Parent:GetChildren()) do
						--		v.CanCollide = false
						--	end
					end		

					local DragBall = createDragBall()
					DragBall.CFrame = mouse.Hit
					Dragger = DragBall

					mouse.TargetFilter = GrabObject

					local DragBallWeld = weldBetween(DragBall,GrabObject)
					addMover(DragBall)


					while Dragger do
						--Create a ray from the users head to the mouse.
						local cf = CFrame.new(character.Head.Position, mouse.Hit.Position)
						Dragger.Mover.Position = (cf + (cf.LookVector * 6)).Position
						Dragger.RotMover.CFrame = camera.CFrame * CFrame.Angles(Dragger.RotOffset.Value.X,Dragger.RotOffset.Value.Y, Dragger.RotOffset.Value.Z)
						task.wait()
					end
					mouse.TargetFilter = nil
				end
			end	
		elseif UserInputState == Enum.UserInputState.End then
			if GrabObject ~= nil then
				if GrabObject.Name == "Main" then
					--for i, v in pairs(GrabObject.Parent:GetChildren()) do
					--	v.CanCollide = true
					--end
				end
			end
			GrabObject = nil
			GrabStart = false
			if Dragger then
				Dragger:Destroy()
				Dragger = nil
			end
		end
	end	
end

-- // Mobile grab function:
local function MobileGrab()
	local PlayerGUI = player.PlayerGui
	local Mouse = player:GetMouse() -- // This works on mobile

	local Magnitude = (mouse.Hit.Position - character.Head.CFrame.Position).magnitude

	local Button = PlayerGUI.PlaceGUI.Drop
	Button.MouseButton1Down:Connect(function()
		PlayerGUI.PlaceGUI.Enabled = false
		GrabModel.PrimaryPart.LocalPizzaPrompt.Enabled = true
		GrabObject = nil
		GrabStart = false
		if Dragger then
			Dragger:Destroy()
			Dragger = nil
		end
		ServicesModule["RunService"]:UnbindFromRenderStep("MovePart")
	end)

	if Magnitude < 10 then

		if mouse.Target then

			GrabObject = mouse.Target
			GrabStart = true

			if GrabObject.Name == "Pizza" or GrabObject.Parent.Name == "Pizza" then
				--print("OBJ")
				--for i, v in pairs(GrabObject.Parent:GetChildren()) do
				--	v.CanCollide = false
				--end
			end					

			local DragBall = createDragBall()
			DragBall.CFrame = mouse.Hit
			Dragger = DragBall

			mouse.TargetFilter = GrabObject

			local DragBallWeld = weldBetween(DragBall,GrabObject)
			addMover(DragBall)

			local cf = CFrame.new(character.Head.Position, mouse.Hit.Position)
			Dragger.Mover.Position = ((cf + (cf.LookVector * 6)).Position + Vector3.new(0, 2, 0))
			Dragger.RotMover.CFrame = camera.CFrame * CFrame.Angles(Dragger.RotOffset.Value.X,Dragger.RotOffset.Value.Y + 2, Dragger.RotOffset.Value.Z)
			
			grabObject()			
			ServicesModule["RunService"]:BindToRenderStep("MovePart", Enum.RenderPriority.Camera.Value, grabObject)
			
			mouse.TargetFilter = nil
		end
	end
end

-- // Mobile init function:
local function Mobile_Init()
	local PC, Touchscreen = (UserInputService.MouseEnabled and UserInputService.KeyboardEnabled), UserInputService.TouchEnabled

	if Touchscreen then
		local NewPrompt = Instance.new("ProximityPrompt")
		NewPrompt.Name = "LocalPizzaPrompt"
		NewPrompt.MaxActivationDistance = 9
		NewPrompt.Parent = workspace.Pizza.PrimaryPart
		NewPrompt.ClickablePrompt = true
		NewPrompt.RequiresLineOfSight = false

		NewPrompt.Triggered:Connect(function()
			NewPrompt.Enabled = false
			player.PlayerGui.PlaceGUI.Enabled = true
			workspace.Pizza:SetPrimaryPartCFrame(workspace.Pizza.PrimaryPart.CFrame + Vector3.new(0, 3, 0))
			MobileGrab()
		end)
	else
		CAS:BindAction("Grab", Grab, false, Enum.UserInputType.MouseButton1)
	end	
end

Mobile_Init()
onCharacterAdded(character)

return PizzaFollowModule

Any help would be greatly appreciated. Also I should stress the pc version of this system works I need to fix the mobile version.

Try just using the script i gave you, then modify it little by little so you know when it starts not working.

also just put it in a local script for a while, It supposed to work for mobile and pc

  • Make sure to add anything inside the part you wanna grab named “CanGrab” (You can modify it as well)
  • AND make sure if youre going to modify the script, just little by little (For troubleshooting purposes)