Snap placement being bias towards specifically 2 sides

I’m not certain how to word this, but my script uses a snapping system that moves parts to multiples of 4 based on player mouses. However, this for some reason, causes parts to move more commonly to 2 specific sides - and fully prevents players from placing parts flat against another side on some situations. It’s easier to understand if I show it to you.

The code looks something like this.

local function roundTo(a, b)

local result = (math.floor(a / b) * b)

return result

end

local roundedTo = 4

local x = roundTo(cframe.X,roundedTo)
local y = roundTo(cframe.Y,roundedTo)
local z = roundTo(cframe.Z,roundedTo)
(it then sets the parts cframe)

Thanks for the help.

1 Like

That’s because you’re using “math.floor()”, you need to use “math.round()” instead.

I doubt my method is at all the best, but here’s how I came up with my solution a while ago:

To start off, I created a Folder in Workspace to hold all of the blocks that were placed down. Each time a block is placed, wouldn’t you guess it, it’s placed inside this folder. So now when the player’s mouse hovers over some BasePart in workspace, I can sort of use a cheat code when I know they’re hovering over a block.

I have this module script here to store some common info on the blocks, but you could just make it a variable if you really wanted to

return {
	GridSize = 4, -- might want to change this to fit your needs (in studs)
	MaxPlaceDistance = 40, -- unsurprisingly also in studs
	Normals = {
		[Enum.NormalId.Back] = Vector3.new(0, 0, 1),
		[Enum.NormalId.Front] = Vector3.new(0, 0, -1),
		[Enum.NormalId.Bottom] = Vector3.new(0, -1, 0),
		[Enum.NormalId.Top] = Vector3.new(0, 1, 0),
		[Enum.NormalId.Left] = Vector3.new(-1, 0, 0),
		[Enum.NormalId.Right] = Vector3.new(1, 0, 0),
	}
}

Now that we have these constants set up, here comes the magic.


If we’re hovering over a block, which we’d know because it’s parent would be that Blocks Folder:

  • Use the mouse.TargetSurface and the Normals table we created to get the direction to offset the block towards

If we’re hovering over a regular part:

  • Do a little “mathy math” to find out where the block should be based on where the mouse is hitting

The function I used for this looked like so:

-- Variable meanings if they aren't super obvious (for the devforum):

-- block -> the actual block that's following my mouse
-- placing -> a bool to define if I'm currently placing a block or not
-- mouse -> player:GetMouse()
-- GRID_SIZE -> 4
-- BlockGlobals -> the module I used, but you could just make it a variable

local function snapGrid()
	if block and placing and mouse.Target then
		if mouse.Target.Parent ~= blocksFolder then
			local vec3 = Vector3.new(
				math.floor(mouse.Hit.p.X / GRID_SIZE + 0.5) * GRID_SIZE,
				mouse.Target.Position.Y + mouse.Target.Size.Y/2 + GRID_SIZE/2,
				math.floor(mouse.Hit.p.Z / GRID_SIZE + 0.5) * GRID_SIZE
			)
			block.Position = block.Position:lerp(vec3, 0.69)
		else
			local targetPos = mouse.Target.Position + Vector3.new(1, 1, 1) * GRID_SIZE * BlockGlobals.Normals[mouse.TargetSurface]
			block.Position = block.Position:lerp(targetPos, 0.69)
		end
	end
end

And basically just run this snapGrid function on a RenderStepped loop and at best you get some semi-optimized prototyping functionality that works like a charm:

https://gyazo.com/d39083c796b356d96e0a90136c4e9501

Side note: this is a pretty old idea of mine and I’m sure someone with a degree of “all things that you shouldn’t do because there are simpler solutions if you really take the time to think about it” will come along and correct me, but this approach works.

1 Like