Y axis Issue on Grid Building System

I made a Grid block building system and everything works fine, except the fact that the block kind of slides on to other blocks?
It’s kind of hard to explain, so here’s a video on what’s happening.


See how the Dummy block slides on an already placed block? I don’t want that. I want it to just either go on the side or stack on top of it.

Here’s the module code:


local BuildModule = {}
BuildModule.__index = BuildModule

local TweenService = game:GetService("TweenService")
local UserInputService = game:GetService("UserInputService")


local DUMMY_BLOCK_TRANSPARENCY = 0.5
local TWEEN_INFO = TweenInfo.new(0.1)
local GRID = 3
local Connections = {}

function BuildModule.new()
	local self = setmetatable({}, BuildModule)
	self.buildingEnabled = false
	self.canPlaceBlock = false
	self.dummyBlock = nil
	self.mouse = game.Players.LocalPlayer:GetMouse()
	return self
end

function BuildModule:toggleBuilding(Part)
	self.buildingEnabled = not self.buildingEnabled
	if self.buildingEnabled then
		self:createDummyBlock(Part)
	else
		Connections = {}
		self:removeDummyBlock()
	end
end

function BuildModule:createDummyBlock(Part)
	self.dummyBlock = Part:Clone()
	self.dummyBlock.Parent = workspace.Parts
end

function BuildModule:removeDummyBlock()
	self.dummyBlock:Destroy()
	self.dummyBlock = nil
end

function BuildModule:updateDummyBlockPosition(newPosition)
	local tween = TweenService:Create(self.dummyBlock, TweenInfo.new(0.1), {Position = newPosition})
	tween:Play()
	tween.Completed:Wait()
end

function BuildModule:placeBlock()
	
	if not self.canPlaceBlock then return end
	local newBlock = self.dummyBlock:Clone()
	newBlock.Transparency = 0
	newBlock.Parent = workspace
	self:toggleBuilding()
end

function BuildModule:init(Part)
	local c1 = self.mouse.Move:Connect(function()
		if not self.buildingEnabled then return end
		local target = self.mouse.Target
		local R = self.mouse.UnitRay
		local Ray = Ray.new(R.Origin, R.Direction * 100000)
		local _,tpos = workspace:FindPartOnRay(Ray)

		if not target or target.Parent == game.Players.LocalPlayer.Character then
			self.dummyBlock.Transparency = 1
			self.canPlaceBlock = false
			return
		elseif target == self.dummyBlock then
			self.canPlaceBlock = true
			return
		else
			
			local x = math.floor(tpos.X / GRID) * GRID
			local y = tpos.Y + self.dummyBlock.Size.Y / 2
			local z = math.floor(tpos.Z / GRID) * GRID
			self:updateDummyBlockPosition(Vector3.new(
				x,
				y,
				z
				))
			self.dummyBlock.Transparency = DUMMY_BLOCK_TRANSPARENCY
			self.canPlaceBlock = true
		end
	end)
	table.insert(Connections, c1)

	UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
		if gameProcessedEvent then return end
		if input.KeyCode == Enum.KeyCode.E then
			self:toggleBuilding(Part)
		elseif input.UserInputType == Enum.UserInputType.MouseButton1 and self.buildingEnabled then
			self:placeBlock()
		end
	end)
end

return BuildModule

Would be amazing if someone knew what I’m doing wrong. I’ve already spent an hour and a half looking at tutorials and testing lmao.

1 Like

What you can do is add the Y size of the mouse’s target to the updated vector.

local mouseTarget = Mouse.Target
local vector = snapToVector(x, y + mouseTarget.Size.Y + 0.1, z)

part.Position = vector

this is a basic implementation of what Im referring to, you can definitely adapt it into your own code

Could you further explain? What would the snapToVector function be?

The functionality looks adequate, so I would just turn the colour of the block to red when it intersects so informing the player that the location is invalid.

Thanks for your feedback. I’ll add that.

Here is a basic implementation I wrote which might help you understand:

function snapToGrid(grid, x)
    -- // WHEREIN: x = Mouse.Hit.Position ; grid = the amt. of studs you want the block to move by (preferrably 2)
    return math.ceil((x/grid ) - 0.5) * grid
end

-- // Use BindToRenderStepped() Instead 
local currentConnection = game:GetService("RunService").RenderStepped:Connect(function()
      local hitPosition = self.MOUSE.Hit.Position
        
        local x = snapToGrid(2, hitPosition.X) 
        local y = Mouse.Target.Size.Y
        local z = snapToGrid(2, hitPosition.Y)
        
        local updated_vector = Vector3.new(x, y + 0.01, z)
        part.Position = updated_vector

        
end)

There are obviously multiple flaws in the code I’ve given above, but it should be enough to give you a basic understanding of what I was reffering to

1 Like

Thanks for clarifying! I’ll try and incorporate it into my script.