Placement System Placing an item more than once

So basically, I have a placement system. The first time I place something down, it places it once. Then, when I place something again, it places it two times, and so on.

Local Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PlaceStructure = ReplicatedStorage:WaitForChild("PlaceStrucutre")
local Structures = ReplicatedStorage:WaitForChild("Structures")

local UIS = game:GetService('UserInputService')
local RunService = game:GetService("RunService")

local player = game.Players.LocalPlayer
local StructureFrame = script.Parent.ScrollingFrame
local char = player.Character or player.Character:Wait()
local HumanoidRootPart = char:WaitForChild("HumanoidRootPart")

local mouse = player:GetMouse()

local yBuildingOffset = 5
local maxPlacingDistance = 50
local rKeyIsPressed = false
local placingStructure = false

for _, structureButtons in pairs(StructureFrame:GetChildren()) do
	if structureButtons:IsA("TextButton") then
		structureButtons.MouseButton1Click:Connect(function()
			
			StructureFrame.Visible = false
			
			local yOrientation = 0
			local goodToPlace = false
			local placedStructure
			
			if placingStructure == false then
				placingStructure = true
				
				local clientStructure = Structures:FindFirstChild(structureButtons.Name):Clone()
				clientStructure.BrickColor = BrickColor.new("Forest green")
				clientStructure.Material = "Neon"
				clientStructure.CanCollide = false
				clientStructure.Parent = game.Workspace
				
				local startingCFrame = CFrame.new(0, -2, -15)
				clientStructure.CFrame = HumanoidRootPart.CFrame:ToWorldSpace(startingCFrame)
				
				RunService.RenderStepped:Connect(function()
					local mouseRay = mouse.UnitRay
					local castRay = Ray.new(mouseRay.Origin, mouseRay.Direction * 1000)
					local ignoreList = {clientStructure, char}
					local hit, position = workspace:FindPartOnRayWithIgnoreList(castRay, ignoreList)
					
					if hit  and (HumanoidRootPart.Position - clientStructure.Position).Magnitude < maxPlacingDistance then
						goodToPlace = true
						clientStructure.BrickColor = BrickColor.new("Forest green")
					else
						goodToPlace = false
						clientStructure.BrickColor = BrickColor.new("Crimson")
						
						
					end
					
					local newAnglesCFrame = CFrame.Angles(0, math.rad(yOrientation), 0)
					local newCFrame = CFrame.new(position.X, position.Y + yBuildingOffset, position.Z)
					clientStructure.CFrame = newCFrame * newAnglesCFrame
				end)
				
				UIS.InputBegan:Connect(function(input)
					if input.KeyCode == Enum.KeyCode.R then
						rKeyIsPressed = true
						
						local rotationSpeed = 5
						while rKeyIsPressed do
							wait()
							if placingStructure == true then
								yOrientation = yOrientation + rotationSpeed
							end
						end
					end
				end)
				
				UIS.InputEnded:Connect(function(input)
					if input.KeyCode == Enum.KeyCode.R then
						rKeyIsPressed = false
					end
				end)
				
				UIS.InputBegan:Connect(function(input)
					if input.UserInputType == Enum.UserInputType.MouseButton1 then
						if placingStructure == true then
							if goodToPlace == true then
								local StructureCFrame = clientStructure.CFrame
								placedStructure = PlaceStructure:InvokeServer(clientStructure.Name, StructureCFrame)
								
								if placedStructure == true then
									placingStructure = false
									clientStructure:Destroy()
									StructureFrame.Visible = true
								end
							end
						end
					end
				end)
			end
		end)
	end
end

Server Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PlaceStructure = ReplicatedStorage:WaitForChild("PlaceStrucutre")
local Strucutres = ReplicatedStorage:WaitForChild("Structures")

PlaceStructure.OnServerInvoke = function(player, StrucutreName, StructureCFrame)
	local crafted
	local realStructure = Strucutres:FindFirstChild(StrucutreName):Clone()
	
	if realStructure then
		realStructure.CFrame = StructureCFrame
		realStructure.Parent = game.Workspace
		crafted = true
	else
		crafted = false
	end
	
	return crafted
end
1 Like

It’s possible that the behavior is related to the name of the part being placed. If the part name is not unique, it’s possible that the code that checks if a part already exists in the workspace may be incorrectly identifying the part as not yet placed, causing it to place multiple times.

I would recommend double-checking the names of the parts being placed to ensure that they are unique and not conflicting with any existing parts in the workspace. Additionally, you can add debug prints to the code to see if the part is being identified as already existing in the workspace when it is being placed multiple times.

1 Like

It looks like you have a functional placement system that allows the player to place structures in the game world. The system is activated when the player clicks on a structure button in the GUI, and a green preview structure is placed in the world. The player can then use the mouse to position and rotate the preview structure, and press the “R” key to rotate it around the y-axis.

When the player clicks the left mouse button, the system sends a request to the server to place the structure. The server script then finds the real structure model in ReplicatedStorage, clones it, and sets its position and orientation to match the preview structure. If successful, the real structure is parented to the game world and the preview structure is destroyed.

Overall, your placement system seems to be working well. If you have any specific questions or issues, feel free to ask!

If I’m seeing this right, you are adding a MouseButton1Click listener function to the TextButtons in your StructureFrame. In that MouseButton1Click function, you are creating a connection to UIS:InputBegan that will actually fire the server. However, you never disconnect that function. So every time the TextButton is clicked, it is creating another connection to UIS:InputBegan. Therefore, the first time you click the TextButton, it creates that connection and fires the server to place a building. The second time you click, you make a new connection and are now placing two buildings because the first connection still exists. Third time, there are now three connections, and so on and so on. I think you can avoid duplicates by creating a variable first, then setting that listener to the variable, and then calling :Disconnect() on the variable after the server is fired. I reread that a couple times over and I think I explained what I’m thinking there…hopefully

1 Like