How would I go with scripting a grid placement system?

Hello everyone, I am making a tycoon game, basically for a part of the tycoon I want players to move things around. I have made a basic placement system before. However, I do not know where to start for a grid placement system.

I don’t know what I would use to make the system. I am pretty bad with CFrames and I am just stuck and blank-minded. Does anyone have any ideas or any resources that can help me? I also am terrible with roblox math, I do have the basics down for raycasting though.

1 Like

I have only a little experience with grid placing, but I believe the answer may be rounding all the cframe values, and then multiplying them by the grid’s size in studs.

1 Like

What CFrame values? The sizes of the placeable objects? But I also don’t know how to make a grid lol.

CFrame stands for CoordinateFrame, keeping the instance’s rotational value and positional value. For this scenario, (assuming you don’t want [insert item here] to pivot off of walls) you only need Vector3, a positional value. The script may look like:

local x_grid = math.round(mouse_hit.p.X)*4 -- Assuming you have the mouse's hit position. 4 is the grid size.
local z_grid = math.round(mouse_hit.p.Z)*4 -- Same as x, skipping y for now.

place_item:SetPrimaryPartCFrame(CFrame.new(x_grid,mouse_hit.p.Y,z_grid)) -- Set the model's position.

This script probably won’t work, but it is an example of how I’d go about doing a grid placing system. This script assumes you have the mouse.hit value, which could be obtained through a RemoteEvent instance. As for the place_item:SetPrimaryPartCFrame(cf), all it does is position a model, assuming the model has a PrimaryPart, which can be set in the properties tab. Note: you may want to set the mouse’s TargetFilter to exclude the models you use for placing, so it doesn’t try to pivot off of what you’re placing

I have not tested this, and I’m pretty sure it’ll fail, (like most first-tries in coding) but I hope you understand the basic idea.

1 Like
local gridSize = 4
local function GetGridPos(Vector)
   return Vector3.new(Vector.X-Vector.X%gridSize,Vector.Y-Vector.Y%gridSize,Vector.Z-Vector.Z%gridSize)
end

Thats a way to get grid position with any vector

2 Likes

Oh well this is Something i used to struggle with back then when i started. Well lets start shall we?

So first take mouses UnitRay

local Mouse = game.Players.LocalPlayer:GetMouse()

Mouse.UnitRay --This thing

Next RaycastParams. You should have a specific space where you CAN place stuff.

local WhereToPlace = {YourPartAlsoMakeSureToMakeThisInATableOrWontWork}
local RayP = RaycastParams.new()
RayP.FilterInstancesDescendants(WhereToPlace)
RayP.FilterType = Enum.RaycastFilterType.Whitelist

--Raycast

local Ray = workspace:Raycast(Mouse.UnitRay.Origin,Mouse.UnitRay.Direction times 1000,RayP)

1 Like

Thanks, it’s finally not confusing, so I believe target filter is what you want the mouse to ignore correct? So I think I would set this to the placed objects?

Thanks, mind explaining this? It seems kind of complicated.

Thats a Modulo Operator.
it returns the reminder of a given division.

print(7%2) -- prints 1 because the closest full number 2 can divide is 6. (7-6=1)
print(8%2) -- prints 0 because 8 can be divided by 2

I see! I am learning a lot.

So I actually edited @inotrandom’s suggestion and it worked VERY well. However it isn’t directly next to the mouse (the part), here it is:

local mouse = game.Players.LocalPlayer:GetMouse()

game:GetService("RunService").RenderStepped:Connect(function()

local x_grid = math.round(mouse.Hit.p.X)*4 -- Assuming you have the mouse's hit position. 4 is the grid size.
	local z_grid = math.round(mouse.Hit.p.Z)*4 -- Same as x, skipping y for now.
	game.Workspace.Part.CFrame = CFrame.new(x_grid,mouse.Hit.p.Y,z_grid) -- Set the model's position.
end)

But also, my biggest question is with all of this, is how I would I make it so the part doesn’t go off the canvas? Would I need an invisible wall or something?

1 Like

Something like this should work. Haven’t given it a test though; last worked with this a couple weeks ago. This resource helped me out.
(Optimizing Multidimensional Arrays With table.create)

local width = 5
local height = 5
local array = table.create(width)
for x = 1,width do
    array[x] = table.create(height)
for y = 1,height do
    array[x][y] = x*y
   end
end
1 Like

Thanks for this, I assume by multiplying the x by the z gives me the area of the top/bottom?

you can just detect if there is a target (mouse.Target), if there is not target, dont render the block

Yea, you could definitely add a third dimension to this. But this on it’s own is just a 2d plane of points, basically. You could now add something like

~~
array[x][y] = x * y
local Part = Instance.new("Part", workspace)
Part.Size = Vector3.new(width, 1, height)
Part.Position = Vector3.new(0,0,0) + Vector3.new(x*width, 0, y*height)
end

Should add parts to visualize the grid. Obviously you’ll need to work out the details yourself!

Alright! I will work on it. I will update you guys on everything goes!

You can check if it is out of a certain range, and if so, disable placing.