Building System Bugs

I’m trying to create a system where players can build cars. It works fine for the first item the player chooses, but when they choose a second item, then there’s a problem. The ghostPart that shows the user where the part will be places, flickers around the screen when the user chooses a second part to place.
Here is a video to show more of what I mean:

Here is the local script:

local inventoryFrame = script.Parent.Parent.InventoryFrame
local button = script.Parent

local basicFunctions = require(game.ReplicatedStorage.Functions.BasicFunctions)

local conversions = require(game.ReplicatedStorage.Conversions)

local placeItem = game.ReplicatedStorage.PlaceItem


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

local player = Players.LocalPlayer
local mouse = player:GetMouse()
local camera = Workspace.CurrentCamera

local matchRotation = true
local gridSize = 1	

local function roundToGrid(value)
	return math.round(value / gridSize) * gridSize
end

local function getPlacementCFrame(ghostPart)
	local origin = camera.CFrame.Position
	local direction = (mouse.Hit.Position - origin).Unit * 1000

	local rayParams = RaycastParams.new()
	rayParams.FilterDescendantsInstances = {player.Character, ghostPart}
	rayParams.FilterType = Enum.RaycastFilterType.Exclude

	local result = workspace:Raycast(origin, direction, rayParams)
	if not result then return nil end

	local hitPos = result.Position
	local normal = result.Normal
	local target = result.Instance

	local up = normal
	local forward
	if math.abs(normal:Dot(Vector3.new(0, 1, 0))) > 0.9 then
		forward = target.CFrame.LookVector
	else
		forward = (camera.CFrame.Position - hitPos)
		forward = Vector3.new(forward.X, 0, forward.Z)
		if forward.Magnitude == 0 then forward = Vector3.new(0, 0, -1) end
		forward = forward.Unit
	end
	local right = forward:Cross(up).Unit
	forward = up:Cross(right).Unit

	local ghostSize = ghostPart.Size
	local offset = ghostSize.Y / 2
	local normalAbs = Vector3.new(math.abs(normal.X), math.abs(normal.Y), math.abs(normal.Z))
	if normalAbs.X > normalAbs.Y and normalAbs.X > normalAbs.Z then
		offset = ghostSize.X / 2
	elseif normalAbs.Z > normalAbs.X and normalAbs.Z > normalAbs.Y then
		offset = ghostSize.Z / 2
	end

	local exactPos = hitPos + normal * offset

	local snappedPos = Vector3.new(
		roundToGrid(exactPos.X),
		roundToGrid(exactPos.Y),
		roundToGrid(exactPos.Z)
	)

	return CFrame.fromMatrix(snappedPos, right, up)
end



local function placePart(id, class)

	local part = conversions.idToPart(id, class)
	local ghostTemplate = part


	local ghostPart = ghostTemplate:Clone()
	ghostPart.Anchored = true
	ghostPart.CanCollide = false
	ghostPart.Transparency = 0.5
	ghostPart.Name = "GhostPart"
	ghostPart.Parent = workspace
	mouse.TargetFilter = ghostPart

	RunService.RenderStepped:Connect(function()
		local cf = getPlacementCFrame(ghostPart)
		if cf then
			ghostPart.CFrame = cf
		end
	end)

	mouse.Button1Down:Connect(function()
		local cf = getPlacementCFrame(ghostPart)

		local ghostPart = ghostTemplate:Clone()
		ghostPart.Anchored = true
		ghostPart.CanCollide = false
		ghostPart.Transparency = 0.5
		ghostPart.Name = "GhostPart"
		ghostPart.Parent = workspace
		mouse.TargetFilter = ghostPart

		placeItem:FireServer(cf, id, class)

	end)
end
button.MouseButton1Click:Connect(function()
	inventoryFrame.Visible = true
	inventoryFrame.Inventory.Text = "Choose a part"

	for _, button:TextButton in basicFunctions.GetAllChildrenWhichAreA(inventoryFrame.ScrollingFrame, "TextButton") do
		button.MouseButton1Click:Connect(function()
			inventoryFrame.Visible = false
			local id = button:GetAttribute("Id")
			local class = button:GetAttribute("Class")

			placePart(id, class)

		end)
	end
end)


1 Like

I think you are making multpile parts that are still being positioned to wherever your mouse hits. you’re also using mouse.TargetFilter to ignore just one ghostblock, this is not something bad if you’re only supposed to have one ghostblock shown, but youre still having multiple blocks being positioned to the mouse position one on top of another because youre creating a RenderStepped connection to each one created.

You can try this

It’s just a rough version i did
but for me it fixed the problem

every time you clicked a new part to place it would double the connections, making both parts move together, causing what happened in the video

I don’t really know how you want your system, so you’ll have to improve on this concept

local currentGhostPart = nil
local steppedConnection = nil
local mouseConnection = nil

local function placePart(id, class)
	
	if currentGhostPart then
		currentGhostPart:Destroy()
		currentGhostPart = nil
		if steppedConnection then
			steppedConnection:Disconnect()
			steppedConnection = nil
		end
		if mouseConnection then
			mouseConnection:Disconnect()
			mouseConnection = nil
		end
	end
	
    local part = conversions.idToPart(id, class)
	local ghostTemplate = part

	local ghostPart = ghostTemplate:Clone()
	ghostPart.Anchored = true
	ghostPart.CanCollide = false
	
	currentGhostPart = ghostPart
	
	ghostPart.Transparency = 0.5
	ghostPart.Name = "GhostPart"
	ghostPart.Parent = workspace
	mouse.TargetFilter = ghostPart

	steppedConnection = RunService.RenderStepped:Connect(function()
		local cf = getPlacementCFrame(ghostPart)
		if cf then
			ghostPart.CFrame = cf
		end
	end)

	mouseConnection = mouse.Button1Down:Connect(function()	
		local cf = getPlacementCFrame(ghostPart)
		
		local ghostPart = ghostTemplate:Clone()
		ghostPart.Anchored = true
		ghostPart.CanCollide = false
		ghostPart.Transparency = 0.5
		ghostPart.Name = "GhostPart"
		ghostPart.Parent = workspace
		mouse.TargetFilter = ghostPart
	end)
end

I’ve implemented this and the main issue still persists.

1 Like

turn off CanQuery for the ghostpart

and check workspace to make sure when you press a new part the old one gets destroyed

Turning off CanQuery fixed the problem! Thanks a bunch!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.