-
What do you want to achieve?
Bassicaly i want make a grid system on my map (using the baseplate as reference to create the grids)
-
What is the issue?
Iam not super good with math, so i need understand how that math will work, i need create the grids just with positions (that i will save on tables), than i will need a math for check if some spell or player is inside some grid using that positions on table.
-
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I tryed look for some tutorials, but i still dont understand how that type of math work.
What do you mean by “grid system”?
I think that it means locking object to a grid in a building system and define “legal” way of placing objects.
In the screenshot bellow you can see legally (green) and illegally (red) placed parts to a grid system:
I might be wrong of course.
like chuncks, like minecraft, chuncks, that.
yes but i will create a grid for the entire map
i pretend save the chuncks positions on tables (to dont be necessay create parts or region 3 for that).
What goes on this grid? A part / model that fits within that grid spot? A bit confused as to what you want to do.
I made blocks placing system, which uses a definied grid. I can share and explain from scratch how I figured it out and how I coded it.
that is fine, how that work, it would be helpful
bassicaly i wont use .touched for my spells hitbox, i will check in what GRID the spell is, and check for spells that are inside that chunck too, that is why i need a grid system.
Well for example, if you have one box where the bottom left corner is position (0,0) and you know the side of each grid box is 2 studs, you can find the bounds of that box like this:
Left Side Bottom Corner: (0,0)
Right Side Bottom Corner (2,0)
Left Side Top Corner: (0,2)
Right Side Top Corner: (2,0)
And then repeat for each after that, if you have another grid to the immediate right of the first grid, just adjust the bottom corners by adding 2 to the first values of both pairs.
than how i would be able to check if some PART is inside that grid? (since i just have the borders positions)
If its less than the right and top most bounds and greater than the left and bottom most bounds.
EX: A position of (1,1) is less than (0,2) in the Y-axis (1 < 2) and greater than (0,0).
what you mean “left most bound”? iam brazilian so i didnt get it.
If the part is inside of a grid box, it must be less than the top Y-axis value and greater than the bottom Y-axis value. In the above example the top y value is 2 and the bottom is 0, so to be within the bounds on the Y-axis it must be between 0 and 2.
Same for the x-axis values.
My blocks basement system uses blocks with size of 3x3x3 studs.
-
Legal x axis:
I noticed that:
if part.Position * 10 % 3 == 0 then it’s legally placed in x axis
else it’s illegally placed in x axis -
Legal y axis:
To make my explanation shorter I will explain the system only for placing on a baseplate.
There is only one legal Position.Y number for legal placement (expection, placing blocks on blocks) -
Legal z axis:
Very similiar to x axis, but with z axis -
My code (local script):
local players = game:GetService("Players")
local player = players.LocalPlayer
local replicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = script.Parent:WaitForChild("RemoteFunction")
local mouse = player:GetMouse()
local tool = script.Parent
local ghostParts = workspace:WaitForChild("GhostParts")
local placeBlockPreview = replicatedStorage:WaitForChild("PlaceBlockPreview")
local character = player.Character
if not character or not character.Parent then
character = player.CharacterAdded:Wait()
end
local humanoid = character:WaitForChild("Humanoid")
local rootPart = character:WaitForChild("HumanoidRootPart")
local baseplate = workspace:WaitForChild("Baseplate")
local buildingModel = workspace:WaitForChild("BuildingModel")
local canUse = true
-- Important for calculating legal x and z position
local function calculateOffset(positionNumber)
if positionNumber * 10 % 3 == 1 then
return -1
elseif positionNumber * 10 % 3 == 2 then
return 1
else
return 0
end
end
mouse.TargetFilter = ghostParts
tool.Equipped:Connect(function()
local clone = placeBlockPreview:Clone()
while tool:FindFirstAncestorOfClass("Model") and humanoid.Health ~= 0 do
local mouseHit = mouse.Hit
local mouseTarget = mouse.Target
local mouseSurface = mouse.TargetSurface
-- In my building system it's used to prevent building outside game's map
local legalPosX = mouseHit.X < 750 and mouseHit.X > -750
local legalPosY = mouseHit.Y < 1507.5
local legalPosZ = mouseHit.Z < 750 and mouseHit.Z > -750
local hitPosition = Vector3.new(mouseHit.X, mouseHit.Y, mouseHit.Z)
local rootPartPosition = rootPart.Position
local distance = (hitPosition - rootPartPosition).magnitude
-- Distance is used to limit player's distance of building
if mouseTarget ~= nil and legalPosX and legalPosY and legalPosZ and distance <= 18 then
-- My building system also uses other types of blocks, don't worry about that
if mouseTarget.Name == "Slab" and mouseTarget:FindFirstChild("SlabBlock") then
mouseTarget = mouseTarget.SlabBlock
elseif mouseTarget.Name == "OnTopSlab" and mouseTarget.Parent.Name == "SlabBlock" then
mouseTarget = mouseTarget.Parent
end
-- This checks if player is pointing with his mouse at an another block or the baseplate
if mouseTarget == baseplate or mouseTarget:FindFirstAncestor("BuildingModel") then
-- This is the most important part because you want to understand how to make grid system on only a baseplate
if mouseSurface == Enum.NormalId.Top then -- Check if mouse is pointing at baseplate's top surface
if mouseTarget == baseplate then
clone.CFrame = mouseHit
-- This is the actual math part. math.floor rounds down every number (examples: 5 to 5, 5.44 to 5, 5.87 also to 5, not 6). I also noticed that the last number of Position.X and Position.Z must be 5 for a block to be legally placed
clone.CFrame = mouseTarget.CFrame:ToWorldSpace(CFrame.new(
math.floor(clone.Position.X) + 0.5 + calculateOffset(math.floor(clone.Position.X) + 0.5),
(mouseTarget.Size.Y + clone.Size.Y) / 2,
math.floor(clone.Position.Z) + 0.5 + calculateOffset(math.floor(clone.Position.Z) + 0.5)
))
else -- Don't worry about that, it's related to placing on other blocks, not baseplate
clone.CFrame = mouseTarget.CFrame:ToWorldSpace(CFrame.new(0, mouseTarget.Size.Y, 0))
end
-- For other surfaces it's also not related to grid on the baseplate
elseif mouseSurface == Enum.NormalId.Right then
clone.CFrame = mouseTarget.CFrame:ToWorldSpace(CFrame.new(mouseTarget.Size.X, 0, 0))
elseif mouseSurface == Enum.NormalId.Left then
clone.CFrame = mouseTarget.CFrame:ToWorldSpace(CFrame.new(-mouseTarget.Size.X, 0, 0))
elseif mouseSurface == Enum.NormalId.Front then
clone.CFrame = mouseTarget.CFrame:ToWorldSpace(CFrame.new(0, 0, -mouseTarget.Size.Z))
elseif mouseSurface == Enum.NormalId.Bottom then
clone.CFrame = mouseTarget.CFrame:ToWorldSpace(CFrame.new(0, -mouseTarget.Size.Y, 0))
elseif mouseSurface == Enum.NormalId.Back then
clone.CFrame = mouseTarget.CFrame:ToWorldSpace(CFrame.new(0, 0, mouseTarget.Size.Z))
end
clone.Parent = ghostParts
end
else
clone.Parent = nil
end
wait()
end
clone:Destroy()
end)
tool.Activated:Connect(function()
-- Player sees a transparent block (placement preview block). After activating the tool, the server gets a request to clone a block from server storage, set the clone's CFrame to preview block CFrame and set it's parent to BuildindModel
if humanoid.Health ~= 0 and ghostParts:FindFirstChild("PlaceBlockPreview") and canUse then
local previewCFrame = ghostParts.PlaceBlockPreview.CFrame
canUse = false
remoteFunction:InvokeServer(previewCFrame)
canUse = true
end
end)
You can ask questions about the code here. I suggest copying the code to Roblox Studio and removing pieces of code, which aren’t related to placing blocks on a baseplate and then reading it.
For people in the future, who find this topic to find a soluion related to the topic, there’s a free model made by me, which is easier to understand: Blocks Placement System to Grid (Like Minecraft) - Roblox.