Why is this preview block bugging out?

I can’t figure out the problem for the preview block for my placement system flickering at random angles and times.
I have tried looking, and haven’t found answers.
Any help would be appreciated.

robloxapp-20240903-2049064.wmv (622.3 KB)

Here is the code:

local Tool = script.Parent
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")
local PlaceModelEvent = ReplicatedStorage:WaitForChild("PlasticBlock")

local modelName = "PlasticBlock1"
local model = ReplicatedStorage:WaitForChild(modelName)
local previewModel
local placeholderPart

-- block color: 163, 162, 165 (RGB)

local function roundToGrid(position, gridSize)
	return Vector3.new(
		math.floor(position.X / gridSize + 0.5) * gridSize,
		math.floor(position.Y / gridSize + 0.5) * gridSize,
		math.floor(position.Z / gridSize + 0.5) * gridSize
	)
end

local function updatePreviewPosition()
	local player = Players.LocalPlayer
	local mouse = player:GetMouse()

	if not mouse.Target then return end

	local gridSize = 3

	local origin = mouse.UnitRay.Origin
	local direction = mouse.UnitRay.Direction * 500

	local raycastParams = RaycastParams.new()
	raycastParams.FilterDescendantsInstances = {player.Character, previewModel}
	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist

	local result = Workspace:Raycast(origin, direction, raycastParams)

	if result then
		local surfaceNormal = result.Normal
		local snapPos = roundToGrid(result.Position + surfaceNormal * (gridSize / 2), gridSize)

		local currentPosition = previewModel.PrimaryPart.Position
		local distance = (currentPosition - snapPos).Magnitude

		if distance > 0.1 then
			previewModel:SetPrimaryPartCFrame(CFrame.new(snapPos))
			placeholderPart.CFrame = CFrame.new(snapPos)
		end
	end
end

local function setPreviewColor(color)
	for _, part in pairs(previewModel:GetDescendants()) do
		if part:IsA("BasePart") then
			part.Color = color
		end
	end
end

Tool.Equipped:Connect(function()l
	previewModel = model:Clone()
	previewModel.Parent = Workspace

	for _, part in pairs(previewModel:GetDescendants()) do
		if part:IsA("BasePart") then
			part.Transparency = 0.5
			part.CanCollide = false
			part.Anchored = true
		end
	end

	placeholderPart = Instance.new("Part")
	placeholderPart.Size = Vector3.new(1, 1, 1)
	placeholderPart.Transparency = 1
	placeholderPart.CanCollide = false
	placeholderPart.Anchored = true
	placeholderPart.Parent = Workspace

	while Tool:IsDescendantOf(Players.LocalPlayer.Backpack) or Tool:IsDescendantOf(Players.LocalPlayer.Character) do
		updatePreviewPosition()
		wait(0.05)
	end
end)

Tool.Unequipped:Connect(function()
	if previewModel then
		previewModel:Destroy()
		previewModel = nil
	end

	if placeholderPart then
		placeholderPart:Destroy()
		placeholderPart = nil
	end
end)

Tool.Activated:Connect(function()
	if not placeholderPart then return end

	local player = Players.LocalPlayer
	local playerPosition = player.Character and player.Character:FindFirstChild("HumanoidRootPart").Position

	if not playerPosition then return end

	local distance = (playerPosition - placeholderPart.Position).Magnitude
	if distance > 15 then -- too far
		setPreviewColor(Color3.new(1, 0, 0))

		wait(0.5)
		setPreviewColor(Color3.fromRGB(163, 162, 165))

		return
	end

	local snapPos = placeholderPart.Position
	local gridSize = 3
	snapPos = roundToGrid(snapPos, gridSize)
	setPreviewColor(Color3.fromRGB(163, 162, 165))

	PlaceModelEvent:FireServer(snapPos)

	Tool:Destroy()
end)

any help would be appreciated on figuring out the problem :slight_smile: