Tool grid placement placing inside existing blocks?

  1. What do you want to achieve? Keep it simple and clear!
    I want to make a simple 2-script tool that allows you to place blocks in a grid.

  2. What is the issue? Include screenshots / videos if possible!
    If you click on the side of a block with my tool, it usually goes inside of the block

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I’ve tried copying the last block placed position and raising the block up if it’s in the last position

**LocalScript**
local Mouse = game.Players.LocalPlayer:GetMouse()
local Positiona
local Limit = 25

script.Parent.Activated:Connect(function()
	local distance = (Mouse.Hit.p - script.Parent.Parent.HumanoidRootPart.Position).Magnitude
	if distance < Limit then
	script.Parent.place:FireServer(Positiona)
	end
end)

Mouse.Move:Connect(function()
	local GridSize = 3
	local X = math.floor((Mouse.Hit.X + GridSize / 2) / GridSize) * GridSize
	local Y = math.ceil((Mouse.Hit.Y + GridSize / 4 ) / GridSize) * GridSize - 1.5
	local Z = math.floor((Mouse.Hit.Z + GridSize / 2) / GridSize) * GridSize
	Positiona = CFrame.new(X, Y, Z)
end)


**Normal Script**
script.Parent.place.OnServerEvent:Connect(function(player, Positiona)
	local pitches = {
		.99,
		.995,
		1,
		1.05,
		1.055
	}
	local finalpitch = pitches[math.random(1, #pitches)]
	script.Parent.Handle.place.PlaybackSpeed = finalpitch
	script.Parent.Handle.place:Play()
	local shape = Instance.new("Part", workspace)
	local tag = Instance.new("StringValue")
	tag.Name = "blockowner"
	tag.Value = player.Name
	tag.Parent = shape
	shape.Size = Vector3.new(3,3,3)
	shape.Material = script.Parent.Handle.Material
	shape.Anchored = true
	shape.Color = script.Parent.Handle.Color
	local soundforbreak = script.Parent.Handle.broken:Clone()
	soundforbreak.Parent = shape
	shape.CFrame = Positiona
end)
1 Like

UPDATE: Only seems to merge with blocks on the bottom of the block, and 2 certain faces of the block.

Please use ``` to make it code lookalike

—LocalScript—
local Mouse = game.Players.LocalPlayer:GetMouse()
local Positiona
local Limit = 25

script.Parent.Activated:Connect(function()
    local distance = (Mouse.Hit.p - script.Parent.Parent.HumanoidRootPart.Position).Magnitude
    if distance < Limit then
       script.Parent.place:FireServer(Positiona)
    end
end)

Mouse.Move:Connect(function()
   local GridSize = 3
   local X = math.floor((Mouse.Hit.X + GridSize / 2) / GridSize) * GridSize
   local Y = math.ceil((Mouse.Hit.Y + GridSize / 4 ) / GridSize) * GridSize - 1.5
   local Z = math.floor((Mouse.Hit.Z + GridSize / 2) / GridSize) * GridSize
   Positiona = CFrame.new(X, Y, Z)
end)
—Normal Script—
script.Parent.place.OnServerEvent:Connect(function(player, Positiona)
   local pitches = {
   .99,
   .995,
   1,
   1.05,
   1.055
}
local finalpitch = pitches[math.random(1, #pitches)]
script.Parent.Handle.place.PlaybackSpeed = finalpitch
script.Parent.Handle.place:Play()
local shape = Instance.new(“Part”, workspace)
local tag = Instance.new(“StringValue”)
tag.Name = “blockowner”
tag.Value = player.Name
tag.Parent = shape
shape.Size = Vector3.new(3,3,3)
shape.Material = script.Parent.Handle.Material
shape.Anchored = true
shape.Color = script.Parent.Handle.Color
local soundforbreak = script.Parent.Handle.broken:Clone()
   soundforbreak.Parent = shape
   shape.CFrame = Positiona
end)

The issue is right here. It works with only positive Vectors.

Here is what im going to do

if u are hitting and existing block then do this.
Use Mouse.TargetSurface to find the normal of the block
it will look something like this

Block.Position = Vector3.fromNormal(Normal) * Block.Size + HitBlock.Position
1 Like

I’ll see what I can do with this, thanks!

Sorry, I am fairly new to the dev forums.

I eventually came up with this piece of half-hacky workaround
if target ~= nil and target:FindFirstChildOfClass(“StringValue”) ~= nil and target:FindFirstChildOfClass(“StringValue”).Value == script.Parent.Parent.Name then
local Normal = Mouse.TargetSurface
if Normal == Enum.NormalId.Bottom then
Positiona += Vector3.new(0,-3,0)
end
if Normal == Enum.NormalId.Right then
Positiona += Vector3.new(3,0,0)
end
if Normal == Enum.NormalId.Back then
Positiona += Vector3.new(0,0,3)
end
end
It isn’t 100% reliable but it works

Thanks everyone for your help!
You can get the model at Simple 2-script grid block building system - Roblox

I ran into the same issue and found this post. I used your solution, but the placement became more offset when the hitBlock was a different size than the placing block. (Works great though if everything’s the same size!)
With your solution, I found that the product of the sum of both block sizes, in half, would remedy this.

hitBlock.Position + (Vector3.FromNormalId(mouse.TargetSurface) * ((hitBlock.Size * .5) + placingBlock.Size * .5))

If you don’t move your mouse you can still place a block inside an existing block after you placed another block, to fix this I just did a for loop to check for every block in workspace and if the block your placing position is the same as another one, it deleted the block your placing.

Thought I would send this incase your having the same issue.

Is it possible to limit how many blocks you can place?

I’m pretty sure you can check the amount of blocks have the value with the player’s name and if it’s over a certain amount of blocks don’t allow them to place.

Or you could add a variable that counts up by 1 every time somebody places and counts down by 1 every time somebody deletes and check if it’s above the limit.