Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
3

How would you go about snapping a CFrame to a grid?

Asked by 2 years ago

Hello! I'm working on a town building game and I want the houses to snap to a grid when being placed. I'm not really sure how to go about this but any help would be appreciated.

P.S. I'm using mouse.UnitRay instead of mouse.Hit.

0
Putting a comment here because I want to know this too! PaleNoobs 37 — 2y

2 answers

Log in to vote
0
Answered by 2 years ago
Edited 2 years ago

I'm not sure how to use UnitRay, and the devforum resources are blocked on my network for now, so I'll just give a quick explanation of how one could go about this.

You could round the mouse's position, and then tween the part to go to the position. An example would be

local plr = game.Players.LocalPlayer
local mouse = plr:GetMouse()
local increment = 4
local dragging
local selected_part

-- This rounding function is primitive, and to be fair, I think there is a better way around this.
-- Of course, the developer forum resources are blocked on my network, so it's not like I can find a better, more efficient rounding system.

local function round(num, multiple)
    local top_value = multiple * math.ceil(num/multiple)
    local low_value = multiple * math.floor(num/multiple)
    if math.abs(top_value - num) < math.abs(low_value - num) then
        return top_value
    elseif math.abs(low_value - num) < math.abs(top_value - num) then
        return low_value
    else
        return low_value
    end
end


mouse.Move:Connect(function()
    if dragging and selected_part then
        local pos = mouse.Hit.Position
        local x_y = {pos.X, pos.Y}
        for i,v in pairs(x_y) do
            x_y[i] = round(v, increment)
        end
        selected_part.Position = Vector3.new(x_y[1], pos.Y, x_y[2])
    end
end)

mouse.Button1Down:Connect(function()
    dragging = not dragging
    selected_part = mouse.Target
end)

In general, just get the mouse's position in worldspace from the unitray, and you can go from there.

0
P.S This is just a simple code example, do not copy and paste this and expect it to 100% work Frometa1998 35 — 2y
0
Isn't there a simpler way to do this? Let's say I already have the CFrame in question and all that's left to do is snap it. How could I go about that? ZakOMGmcpe564 52 — 2y
0
Just round the CFrame value to the nearest 4th. THe round function was overcomplicated since I had no idea how to round in Lua. Frometa1998 35 — 2y
Ad
Log in to vote
0
Answered by 2 years ago

First of all, I don't recommend using mouse.unitRay because it is quite expensive to cast a ray from the player's camera to the mouse position. You should use mouse.Hit for calculating the X and Z position of the object you want to place instead. As for the Y position, you should use mouse.Target because you want to know the position and size of the object you are hovering over.

You may refer to this image I made regarding the concept of calculating the Y position of the object you want to place: https://gyazo.com/f034a03bb1a350d950c225a286905fee (In this case, obj 2's pos and size will be mouse.Target.Position and mouse.Target.Size)

As for the X and Z positions, you may refer to this image I made regarding the concept: https://gyazo.com/50f082f5c374040b9400007bb347632e . In the image, there's a formula "obj's z pos = math.round(mouse.Hit.Z / grid cell size) * grid cell size".What "math.round(mouse.Hit.Z / grid cell size)" is doing is basically getting the cell number to determine which cell should the object be placed on in the grid space. After that, you want to multiply by grid cell size back to determine which cell should the object be placed on in the world space, then set the object's position to the cell's position.

If you really want to use mouse.unitRay, then you will have to find a way to convert mouse.Hit into that, but the concept will still be the same though.

0
I need to ignore two things when the structure is being placed; the ghost structure and the player. Unfortunately with mouse.Hit, it only allows me to ignore one thing. ZakOMGmcpe564 52 — 2y
0
That's simple, you can put all these two things inside a folder or a model, then use mouse.TargetFilter to ignore everything inside that folder/model. It will look something like mouse.TargetFilter = workspace:WaitForChild("Folder") guest_20I8 266 — 2y
0
By the way, the images you sent are blocked on my end. ZakOMGmcpe564 52 — 2y
0
Oo, try copy and paste the links into ur browser guest_20I8 266 — 2y

Answer this question