Help disconnecting connections

Hey, so I’m working on a block placement game, similar to Minecraft. There is a build mode and a delete mode. Both are toggled via TextButtons. When build mode is enabled, it works flawlessly. Blocks are placed as they should be. Then if you switch to delete mode, build mode stops functioning (this is intended behavior, as you can’t be building and deleting blocks at the same time) Delete mode removes the blocks you tap on. The issue comes once you switch back to build mode after using delete mode. It now deletes and places blocks simultaneously. I asked ChatGpt about this issue and it said I need to disconnect my connections. It then provided me with a revised version of my code implementing this. The code it provided me has the same issue as I was having.

I do however believe it is correct about the connections being responsible for this bug. It just failed to properly implement it. I will post my code, with chatGpt’s revision down below. I do not know how connections work. If anyone could take a look at my code, that would be amazing. The code will probably make you cringe as I’m a beginner scripter. I’m sure there is a lot that isn’t efficient and very messy. I’m open to constructive criticism on how to improve the rest of my code. But my primary goal in this post is to fix this bug.

The connections are at the bottom of the script, but the rest of the script may also be a part of the issue.

Thank you so much to anyone who actually looks through this script, I know it long and I appreciate you taking the time to help me :slight_smile:

Local Script (This is the script that the issue is likely coming from)

-- // Declarations

local LocalPlayer = game.Players.LocalPlayer
local replicatedStorage = game:GetService("ReplicatedStorage")
local mouse = LocalPlayer:GetMouse()

local selectorGui = script.Parent.Parent.Parent.BlockSelector

local block = LocalPlayer.PlayerGui:WaitForChild("Block")

local enabled = true
local currentBlock = nil  -- To keep track of the current block


-- // Delete Declarations
local deleteButton = script.Parent.Parent.Delete
local deleteMode = false
deleteBounce = false
local deleteEvent = replicatedStorage:WaitForChild("Remotes"):WaitForChild("DeleteEvent")

local function showSelectorGui()
	selectorGui.Enabled = true
	deleteMode = false
end

script.Parent.MouseButton1Click:Connect(showSelectorGui)





local function updateBlockPreview()
	print(deleteMode)
	
	-- // Prevents player from placing blocks from the other side of the map
	if (LocalPlayer.Character.HumanoidRootPart.Position - mouse.Hit.p).Magnitude > 20 or deleteMode == true then 
		if currentBlock then
			currentBlock:Destroy()
		end
		return end
	-- // Ensures there is only one update block at a time, not thousands
	if currentBlock then

		currentBlock:Destroy()  -- Destroy the current block if it exists
		currentBlock = nil  -- Reset the current block
	end
	-- // Create a previewBlock
	local blockTemplate = replicatedStorage.Blocks:FindFirstChild(block.Value)
	if enabled and blockTemplate then
		local previewBlock = blockTemplate:Clone()
		previewBlock.CanCollide = false
		previewBlock.Transparency = 0.5

		local descendants = previewBlock:GetDescendants()

		-- // Make the previewBlock partially transparent
		for i, v in pairs(descendants) do
			if v:IsA("Decal") then
				v.Transparency = 0.5
			end
		end

		mouse.TargetFilter = previewBlock
		previewBlock.Parent = workspace.PreviewBlocks

		-- // Place it accurately on a grid
		local offset = Vector3.new(0, 0, 0)
		if mouse.TargetSurface == Enum.NormalId.Back then
			offset = Vector3.new(0, 0, 3)
		elseif mouse.TargetSurface == Enum.NormalId.Front then
			offset = Vector3.new(0, 0, -3)
		elseif mouse.TargetSurface == Enum.NormalId.Top then
			offset = Vector3.new(0, 3, 0)
		elseif mouse.TargetSurface == Enum.NormalId.Bottom then
			offset = Vector3.new(0, -3, 0)
		elseif mouse.TargetSurface == Enum.NormalId.Right then
			offset = Vector3.new(3, 0, 0)
		elseif mouse.TargetSurface == Enum.NormalId.Left then
			offset = Vector3.new(-3, 0, 0)
		end

		previewBlock.Position = mouse.Target.Position + offset
		currentBlock = previewBlock  -- Set the current block to the newly created one
	end
end

mouse.Move:Connect(updateBlockPreview)

-- // This function places a block on the server, which all players can see.
local function placeBlock()
	if enabled and mouse.Target and mouse.Target.Name then
		if (LocalPlayer.Character.HumanoidRootPart.Position - mouse.Hit.p).Magnitude > 20 or deleteMode == true then
			return end
		-- // Fire the remote event
		replicatedStorage.Remotes.PlaceEvent:FireServer(mouse.Target, mouse.TargetSurface, block.Value)
	else
		print('Conditions not met')
	end
end

mouse.Button1Down:Connect(placeBlock)


local deleteEventConnection = nil  -- Add this line to keep track of the connection

local function delete()
	deleteMode = true  -- Toggle deleteMode

	if deleteMode  == true then
		-- Connect the event only when deleteMode is true
		deleteEventConnection = mouse.Button1Down:Connect(function()
			if mouse.Target and mouse.Target.Name and mouse.Target.Parent == workspace.Blocks and deleteBounce == false then
				deleteBounce = true
				deleteEvent:FireServer(mouse.Target)
				wait(0.1)
				deleteBounce = false
			end
		end)
	else
		-- Disconnect the event when deleteMode is false
		if deleteEventConnection then
			deleteEventConnection:Disconnect()
		end
	end
end

deleteButton.MouseButton1Click:Connect(delete)







Server Script: (I don’t think this script is very relevant to the issue)

local replicatedStorage = game:GetService("ReplicatedStorage")
local placeEvent = replicatedStorage:WaitForChild("Remotes"):WaitForChild("PlaceEvent")
local deleteEvent = replicatedStorage:WaitForChild("Remotes"):WaitForChild("DeleteEvent")

-- // Place a block
placeEvent.OnServerEvent:Connect(function(player, target, target_surface, block_type)
	local blockTemplate = replicatedStorage.Blocks:FindFirstChild(block_type) 
	if blockTemplate then
		local newBlock = blockTemplate:Clone()
		newBlock.Parent = workspace.Blocks

		local offset = Vector3.new(0, 0, 0)
		if target_surface == Enum.NormalId.Back then
			offset = Vector3.new(0, 0, 3)
		elseif target_surface == Enum.NormalId.Front then
			offset = Vector3.new(0, 0, -3)
		elseif target_surface == Enum.NormalId.Top then
			offset = Vector3.new(0, 3, 0)
		elseif target_surface == Enum.NormalId.Bottom then
			offset = Vector3.new(0, -3, 0)
		elseif target_surface == Enum.NormalId.Right then
			offset = Vector3.new(3, 0, 0)
		elseif target_surface == Enum.NormalId.Left then
			offset = Vector3.new(-3, 0, 0)
		end
		
		
		newBlock.Position = target.Position + offset
	else
		print("Block template not found for type: " .. block_type)
	end
end)

-- // Delete the target block
deleteEvent.OnServerEvent:Connect(function(player, target)
	target:Destroy()
end)

I decided to use a Christian cross to show the actual issue itself since it’s a simple build.

Build mode:

Delete Mode: (deleted the bottom block)

Switching back to build mode after deleting: (I clicked on the far-left block. It deleted the block that was originally there and placed a new one in front of it, this is the primary bug)

Feel free to ask any questions about the scripts and or how the placement system works.

Any feedback/suggestions are much appreciated, thanks!

This always guarantee that event is connected because you set deleteMode to true before running if statement, making disconnection (else statement) not run, but that’s not really the problem here. Let’s look at the else statement:

This will need to be moved to the showSelector button due to the fact that you need this to stop when switching back to building mode. I hope this helps!

1 Like

That was the issue, thank you very much for your help!

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