How do I fix meshes from twitching in grab script?

  1. What do you want to achieve?
    To make the grabbing mesh no longer twitch
  2. What is the issue?
    When I grab a food mesh in my cooking game out of a box and get close to wall/part, it twiches and noclips through it sometimes. The scroll is messing with this and do not know how to solve it
  3. What solutions have you tried so far?
    I have tried fixing it by calculating how far the banana is to the part but did not work

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")

local player = Players.LocalPlayer
local mouse = player:GetMouse()
local event = ReplicatedStorage:WaitForChild("HoldItemEvent")
local camera = workspace.CurrentCamera

local holding = false
local heldPart = nil

local minDistance = 5
local maxDistance = 15
local distance = 5
local targetDistance = distance

local currentRotation = CFrame.Angles(0,0,0)
local targetRotation = CFrame.Angles(0,0,0)
local ROTATION_LERP_ALPHA = 0.25
local ROTATION_AMOUNT_DEGREES = 45

mouse.Button1Down:Connect(function()
	if not player.Character or not player.Character:FindFirstChild("HumanoidRootPart") then return end
	local target = mouse.Target
	if not target then return end
	local model = target:FindFirstAncestor("Bananas")
	if model and model:FindFirstChildWhichIsA("ClickDetector") then
		if not holding then
			local modelCenter = model:GetBoundingBox().Position
			local charPos = player.Character.HumanoidRootPart.Position
			local distFromCharToModel = (charPos - modelCenter).Magnitude
			targetDistance = math.clamp(distFromCharToModel, minDistance, maxDistance)
			distance = targetDistance
			event:FireServer("pickup", {position = mouse.Hit.Position})
			holding = true
			currentRotation = CFrame.Angles(0,0,0)
			targetRotation = CFrame.Angles(0,0,0)
		end
	elseif holding then
		event:FireServer("drop")
		holding = false
		targetDistance = 5
		heldPart = nil
	end
end)

event.OnClientEvent:Connect(function(action, data)
	if action == "heldModel" then
		heldPart = data
	end
end)

UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if gameProcessed or not holding then return end

	if input.KeyCode == Enum.KeyCode.T then
		local direction = camera.CFrame.LookVector
		local charPos = player.Character.HumanoidRootPart.Position
		local throwPosition = charPos + direction * targetDistance

		holding = false
		targetDistance = 5
		heldPart = nil

		event:FireServer("throw", {pos = throwPosition, dir = direction})
	end
end)

UserInputService.InputChanged:Connect(function(input)
	if not holding then return end
	if input.UserInputType == Enum.UserInputType.MouseWheel then
		targetDistance = math.clamp(targetDistance + input.Position.Z, minDistance, maxDistance)
	end
end)

RunService.RenderStepped:Connect(function()
	if holding and player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
		distance = distance + (targetDistance - distance) * 0.25

		local isFirstPerson = (camera.CFrame.Position - camera.Focus.Position).Magnitude < 1
		local root = player.Character.HumanoidRootPart
		local origin, direction

		if isFirstPerson then
			local ray = camera:ScreenPointToRay(mouse.X, mouse.Y)
			origin = ray.Origin
			direction = ray.Direction.Unit
		else
			origin = root.Position + Vector3.new(0, 2.5, 0)
			if mouse.Target and mouse.Hit then
				direction = (mouse.Hit.Position - origin).Unit
			else
				direction = root.CFrame.LookVector
			end
		end

		local rayParams = RaycastParams.new()
		rayParams.FilterDescendantsInstances = {player.Character}
		if heldPart then
			table.insert(rayParams.FilterDescendantsInstances, heldPart)
		end
		rayParams.FilterType = Enum.RaycastFilterType.Blacklist

		local function raycastIgnoreNonCollidable(origin, direction, distance, params)
			local raycastParams = params or RaycastParams.new()
			local currentOrigin = origin
			local maxDistance = distance

			while maxDistance > 0 do
				local result = workspace:Raycast(currentOrigin, direction * maxDistance, raycastParams)
				if not result then
					return nil
				end
				if result.Instance and result.Instance.CanCollide then
					return result
				else
					local traveled = (result.Position - currentOrigin).Magnitude
					maxDistance -= traveled + 0.01
					currentOrigin = result.Position + direction * 0.01
				end
			end
			return nil
		end

		local raycast = raycastIgnoreNonCollidable(origin, direction, distance, rayParams)
		local finalPos = origin + direction * distance
		if raycast then
			finalPos = raycast.Position
		end

		currentRotation = currentRotation:Lerp(targetRotation, ROTATION_LERP_ALPHA)

		local desiredObjectCFrame
		if isFirstPerson then
			desiredObjectCFrame = CFrame.new(finalPos) * CFrame.fromMatrix(
				Vector3.new(0,0,0),
				camera.CFrame.RightVector,
				camera.CFrame.UpVector,
				-camera.CFrame.LookVector
			) * currentRotation
		else
			desiredObjectCFrame = CFrame.new(finalPos) * CFrame.fromMatrix(
				Vector3.new(0,0,0),
				camera.CFrame.RightVector,
				camera.CFrame.UpVector,
				-camera.CFrame.LookVector
			) * currentRotation
		end

		event:FireServer("update", {
			position = desiredObjectCFrame.Position,
			rotationCFrame = desiredObjectCFrame
		})
	end
end)

Just offset the finalPos by the scale of the object. The entire reason its “twitching” is because its attempting to be forced into another object.

finalPos = raycast.Position + (raycast.Normal * heldObject.Size.Magnitude)

You may have to divide the size, but overall that should majorly reduce jittering. Of course though, there will still be some cases where it’ll happen but they’ll be somewhat forced, such as holding an item right in the corner between 2 adjacent walls/floors/ceilings.
If it jitters with the player, then use CollisionGroups that have no collision with the player and that’ll fix it.

I’ll also add that to avoid it jittering though objects when you move it under something, you should maybe make the item auto-drop itself if the player loses line-of-sight to it.

I tried it and it is still glitching a lot. I am trying to replicate a cooking game that fixes this issue by making it not move any more in the direction its trying to go to. So imagine a flat part and I put the food on top and try to drag it through it. It should not try to move downwards since it would clip through it