Collisions with block

good one

Your Z Position should be the CFrame Position of the Part the mouse hits, so Mouse.Target, not the mouse hit.
Do all your calculations based on the CFrame Position and Size of the Target as well as the size of the preview Part you are placing. If all your Parts are the same size don’t calculate based on the Size of the Part, just use the number that’s 1 space on the grid. This means if all your blocks are 4 studs then use 4 studs for placement because that’s the calculation of your grid.

Also, use math.round(mouse.Target.Position.Z) because math.round(mouse.Target.Position.Z/1)*1) is exactly the same value.

If you want more information I’ve seen plenty of grid placement posts on the forums. Try the Search button up top to find better answers than I can give.

srry bro i was dead alseep when you answered :skull:
you can either find egomooses or try mine
the grid system your trying to make is at the top just go to the bottom for mine
but it works with raycasts

local position = target.Position + normal * target.Size.Z

Can you give a code example?

This one does the grid, if I remove that it wont work anymore

@GAGA12345677 Ill try yours

The 2 give the exact same value, let’s say 1.445 as the mouse.Target.Position.Z.

math.round(1.448) is 1
math.round(1.448 / 1) * 1 is 1

It looks like you’ve modified a line of code someone else has suggested that is designed to round to however many decimal places you want. Let’s take the same example of 1.448 rounded to 2 decimal places. Instead of using 1 you’d use 100 in the equation.

math.round(1.448 * 100) / 100 would give 1.45

For a grid system you’d need to use the formulas in @GAGA12345677’s link.

When I modify the code, it breaks.

Who are you replying to? If you reply to yourself then we don’t see the reply. I just happened to get the notice that someone had posted on the thread.

If you’ve modified the code then give us your new modified code so we can help. We can’t read your mind so we can’t tell if you just had a small spelling error or you have extra or not enough code.

Telling us ‘When I modify the code, it breaks’ is like taking a car to a mechanic and saying ‘Something is broken’.

The code I gave was just to let you know your line of code had too much stuff in it and possibly why it was there. I didn’t mean for you to change the line to anything other than math.round(mouse.Target.Position.Z)

You can always utilize collisiongroups for specific collisions

local PhysicsService = game:GetService("PhysicsService")

local function toggleCollision(object1, object2, enableCollision)
    local collisionGroupName = "collisiongroupname" -- set collisiongroup name (optional)

    local object1CollisionGroupId = PhysicsService:GetCollisionGroupId(object1.Name)
    local object2CollisionGroupId = PhysicsService:GetCollisionGroupId(object2.Name)

    if object1CollisionGroupId and object2CollisionGroupId then
        local isCollisionEnabled = PhysicsService:CollisionGroupsAreCollidable(object1CollisionGroupId, object2CollisionGroupId)

        if enableCollision and not isCollisionEnabled then
            PhysicsService:CollisionGroupSetCollidable(collisionGroupName, object1.Name, object2.Name, true)
        elseif not enableCollision and isCollisionEnabled then
            PhysicsService:CollisionGroupSetCollidable(collisionGroupName, object1.Name, object2.Name, false)
        end
    end
end
local RunService = game:GetService("RunService")

-- the blocks you want to check for hovering
local block1 = game.Workspace.Block1
local block2 = game.Workspace.Block2

local hoveringThreshold = 1 -- adjust this value based on how close the blocks need to be to be considered hovering

local function areBlocksHovering(block1, block2)
    local distance = (block1.Position - block2.Position).magnitude
    return distance <= hoveringThreshold
end

local function updateHovering()
    local hovering = areBlocksHovering(block1, block2)
    toggleCollision(block1, block2, not hovering)
end

RunService.Heartbeat:Connect(updateHovering)

I forgot the script here it is

local stuff = game.ReplicatedStorage:WaitForChild("Folder")
local event = game.ReplicatedStorage:WaitForChild("RemoteEvent")
local tool = script.Parent

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local mouse = player:GetMouse()
local uis = game:GetService("UserInputService")
local runservice = game:GetService("RunService")

local place = false
local rotate = false

local rotateamount = 0

function reset()
	if place == false then
		place = true
		preview = stuff:FindFirstChild(tool.Name):Clone()
		preview.Parent = workspace

		for i, parts in pairs(preview:GetDescendants()) do
			if parts:IsA("BasePart") then
				local boundingbox = Instance.new("SelectionBox")
				boundingbox.Parent = parts
				boundingbox.Adornee = parts
				parts.CanCollide = false
			end
		end

		uis.InputBegan:Connect(function(input, gameproccessed)
			if not gameproccessed then
				if input.KeyCode == Enum.KeyCode.R then
					rotate = true
					rotateamount += 10
				end
			end
		end)

		uis.InputEnded:Connect(function(input, gameproccessed)
			if input.KeyCode == Enum.KeyCode.R then
				rotate = false
			end
		end)

		uis.InputBegan:Connect(function(input, gameproccessed)
			if not gameproccessed then
				if input.UserInputType == Enum.UserInputType.MouseButton2 then
					rotateamount = 0
				end
			end
		end)

		runservice.RenderStepped:Connect(function()
			if place == true then
				mouse.TargetFilter = preview

				if preview:FindFirstChild("MainPart") then
					local cframe = CFrame.new(math.round(mouse.hit.Position.X/1)*1, mouse.hit.Position.Y + preview.PrimaryPart.Size.Y/2, math.round(mouse.hit.Position.Z/1)*1)
					local angles = CFrame.Angles(0, math.rad(rotateamount), 0)

					preview:SetPrimaryPartCFrame(cframe * angles)
				end
			end
		end)
	end
end

tool.Equipped:Connect(function()
	place = true

	preview = stuff:FindFirstChild(tool.Name):Clone()
	preview.Parent = workspace

	for i, parts in pairs(preview:GetDescendants()) do
		if parts:IsA("BasePart") then
			local boundingbox = Instance.new("SelectionBox")
			boundingbox.Parent = parts
			boundingbox.Adornee = parts
			parts.CanCollide = false
		end
	end

	uis.InputBegan:Connect(function(input, gameproccessed)
		if input.KeyCode == Enum.KeyCode.R then
			rotate = true
			rotateamount += 10
		end
	end)

	uis.InputEnded:Connect(function(input, gameproccessed)
		if input.KeyCode == Enum.KeyCode.R then
			rotate = false
		end
	end)

	runservice.RenderStepped:Connect(function()
		if place == true then
			mouse.TargetFilter = preview

			if preview:FindFirstChild("MainPart") then
				local cframe = CFrame.new(math.round(mouse.hit.Position.X/1)*1, mouse.hit.Position.Y + preview.PrimaryPart.Size.Y/2, math.round(mouse.hit.Position.Z/1)*1)
				local angles = CFrame.Angles(0, math.rad(rotateamount), 0)

				preview:SetPrimaryPartCFrame(cframe * angles)
			end
		end
	end)

	uis.InputEnded:Connect(function(input, gameproccessed)
		if input.KeyCode == Enum.KeyCode.R then
			rotate = false
		end
	end)

	runservice.RenderStepped:Connect(function()
		if place == true then
			mouse.TargetFilter = preview

			if preview:FindFirstChild("MainPart") then
				local cframe = CFrame.new(math.round(mouse.hit.Position.X/1)*1, mouse.hit.Position.Y + preview.PrimaryPart.Size.Y/2, math.round(mouse.hit.Position.Z/1)*1)
				local angles = CFrame.Angles(0, math.rad(rotateamount), 0)

				preview:SetPrimaryPartCFrame(cframe * angles)
			end
		end
	end)
end)

tool.Activated:Connect(function()
	if place == true then
		place = false

		event:FireServer(preview.Name, preview.PrimaryPart.CFrame)

		preview:Destroy()

		wait(.1)

		reset()
	end
end)

tool.Unequipped:Connect(function()
	preview:Destroy()
end)

Where should I put the code?

local tool = script.Parent

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local mouse = player:GetMouse()
local uis = game:GetService("UserInputService")
local runservice = game:GetService("RunService")

local place = false
local rotate = false
local rotateamount = 0
local preview

function reset()
	if place == false then
		place = true
		preview = game.ReplicatedStorage.Folder[tool.Name]:Clone()
		preview.Parent = workspace

		for _, parts in ipairs(preview:GetDescendants()) do
			if parts:IsA("BasePart") then
				local boundingbox = Instance.new("SelectionBox")
				boundingbox.Parent = parts
				boundingbox.Adornee = parts
				parts.CanCollide = false
			end
		end
	end
end

tool.Equipped:Connect(function()
	reset()

	local rConn1, rConn2, rConn3

	rConn1 = uis.InputBegan:Connect(function(input, gameProcessed)
		if not gameProcessed then
			if input.KeyCode == Enum.KeyCode.R then
				rotate = true
				rotateamount = rotateamount + 10
			end
		end
	end)

	rConn2 = uis.InputEnded:Connect(function(input, gameProcessed)
		if input.KeyCode == Enum.KeyCode.R then
			rotate = false
		end
	end)

	rConn3 = uis.InputBegan:Connect(function(input, gameProcessed)
		if not gameProcessed then
			if input.UserInputType == Enum.UserInputType.MouseButton2 then
				rotateamount = 0
			end
		end
	end)

	runservice:BindToRenderStep("ToolRenderStep", Enum.RenderPriority.First.Value, function()
		if place then
			mouse.TargetFilter = preview

			local mainPart = preview:FindFirstChild("MainPart")
			if mainPart then
				local cframe = CFrame.new(math.round(mouse.Hit.Position.X / 1) * 1, mouse.Hit.Position.Y + mainPart.Size.Y / 2, math.round(mouse.Hit.Position.Z / 1) * 1)
				local angles = CFrame.Angles(0, math.rad(rotateamount), 0)

				mainPart.CFrame = cframe * angles
			end
		end
	end)
end)

tool.Activated:Connect(function()
	if place then
		place = false

		local event = game.ReplicatedStorage.RemoteEvent
		event:FireServer(preview.Name, preview.PrimaryPart.CFrame)

		preview:Destroy()
		preview = nil

		reset()
	end
end)

tool.Unequipped:Connect(function()
	if preview then
		preview:Destroy()
		preview = nil
	end
end)

local PhysicsService = game:GetService("PhysicsService")
local block1 = game.Workspace.Block1
local block2 = game.Workspace.Block2
local hoveringThreshold = 1

local function areBlocksHovering(block1, block2)
	local distance = (block1.Position - block2.Position).magnitude
	return distance <= hoveringThreshold
end

local function toggleCollision(object1, object2, enableCollision)
	local collisionGroupName = "collisiongroupname" -- set collision group name (optional)

	local object1CollisionGroupId = PhysicsService:GetCollisionGroupId(object1.Name)
	local object2CollisionGroupId = PhysicsService:GetCollisionGroupId(object2.Name)

	if object1CollisionGroupId and object2CollisionGroupId then
		local isCollisionEnabled = PhysicsService:CollisionGroupsAreCollidable(object1CollisionGroupId, object2CollisionGroupId)

		if enableCollision and not isCollisionEnabled then
			PhysicsService:CollisionGroupSetCollidable(collisionGroupName, object1.Name, object2.Name, true)
		elseif not enableCollision and isCollisionEnabled then
			PhysicsService:CollisionGroupSetCollidable(collisionGroupName, object1.Name, object2.Name, false)
		end
	end
end

local function updateHovering()
	local hovering = areBlocksHovering(block1, block2)
	toggleCollision(block1, block2, not hovering)
end

game:GetService("RunService").Heartbeat:Connect(updateHovering)

i merged it with the code you provided see if it works or not also i made some changes to the code due to being less efficient and made it more efficient and for you to underestand

you can put it on the same script but i recommend using another script for it to work as i suppose you are using a local script, physics service are only used in server scripts.

if you have anymore questions feel free to ask

It’s in a local script

yeah so you have to separate my part of the script to a server script in order to make it work

if you need to see if blocks collided with eachother you can call remotefunctions