Hello, I've been attemping to make a placement system that sort of emulates the Stamper Tool's placement. Everytime I've attempted it, I've gotten the overall premise down but it doesn't seem to work properly or work as I would like it to.
My current version, works perfectly fine, but the blocks aren't being positioned correctly, if you place down one block, and try to put another one on the side of that block, it'll go inside rather than going to the side.
Same thing applies for models.
Here is how the position is determined currently.
local grid = 4 local function RoundToNearest(ToRound, Increment) return floor(ToRound / Increment + 0.5) * Increment end local function snap() local positon = mouse.Hit.p return CFrame.new(RoundToNearest(positon.X, grid), RoundToNearest(positon.Y, grid) + 2, RoundToNearest(positon.Z, grid)) end
My question is, how would I edit my current code or make a placement system without raycasting that would allow me to place blocks on all faces of another block freely?
Before I give out an answer, allow me to explain how I will solve this problem:
We will be using Mouse.TargetSurface, Vector3.fromNormalId, and Mouse.Target
to solve this problem. Click on the links if you don't know what these are.
By doing Vector3.fromNormalId(Mouse.TargetSurface)
and assuming if the TargetSurface is Top, You will get Vector3.new(0, 1, 0)
, which is the direction to the top.
By doing Vector3.fromNormalId(Mouse.TargetSurface) * grid
though, will give us pretty much the same except the result is multiplied by four, which is Vector3.new(0, 4, 0)
. Now this will be the new block's offset from the block you clicked.
Now we'll do Vector3.fromNormalId(Mouse.TargetSurface) * grid + Mouse.Target.Position
, and this will be the new block's position we can get by using the clicked surface and some math!
Unfortunately, we can only use this math on a surface that is 4 by 4 studs or it's going to position weirdly.
Replace the snap
function to this:
local function snap() local position = mouse.Hit.p local target = mouse.Target local surface = mouse.TargetSurface if target.Size == Vector3.new(grid, grid, grid) then return CFrame.new(Vector3.FromNormalId(surface) * grid + target.Position) end return CFrame.new(RoundToNearest(position.X, grid), RoundToNearest(position.Y, grid) + 2, RoundToNearest(position.Z, grid)) end