What do you want to achieve? Keep it simple and clear!
I want to place blocks based on a grid system.
I have a table named Blocks = {}
when i place a block i create a new table that is inside the table “Blocks = {}”.
code looks like this
local Blocks = {}
local function roundToStep(pos : Vector3)
return Vector3.new(math.floor(pos.X/3)*3+1.5,math.floor(pos.Y/3)*3+1.5,math.floor(pos.Z/3)*3+1.5)
end
function GridSystem.PlaceBlock(pos,color,material)
local block = Instance.new("Part")
block.Parent = workspace.Blocks
block.Position = roundToStep(pos)
block.Size = Vector3.new(3,3,3)
block.Anchored = true
block.Color = color
block.Material = material
local innerTable = {part=block,position=roundToStep(pos)}
table.insert(Blocks, t)
end
What is the issue? Include screenshots / videos if possible!
the issue is that i want to use loops as less as possible to make my game less laggy, I dont want to place a block in a position that already exists in the Block table(to prevent placeing a block on the same position as another block) and to remove the block that has the position associated with the part.
i prefer to use table.find instead of looping because looping makes the game slower if i want to loop through a lot of blocks.
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
i cant think of a solution without using loops, what if i have 500 blocks in game? i dont want to loop through all the blocks
You need loops for this. But don’t worry; loops are efficient! What you need is an array of arrays.
You need to pick how many rows and columns you want. Then for every X from 1 to #rows, you set grid[x] to {}. Within that for loop, you do another for-loop for Y from 1 to #columns, you set grid[x][y] to the block instance.
-- Function to generate a 2D grid
local function generateGrid(rows, cols)
local grid = {}
for x = 1, rows do
grid[x] = {} -- Create a new row
for y = 1, cols do
grid[x][y] = 0 -- Initialize each cell with a default value. You can spawn a black here.
end
end
return grid
end
-- Example: Create a 3x3 grid
local rows = 3
local cols = 3
local myGrid = generateGrid(rows, cols)
-- Print the generated grid
for i = 1, rows do
for j = 1, cols do
print(myGrid[i][j] .. " ")
end
print("\n")
end
You’d also need to position every part to Vector3.new(x,0,y). Make sure you also take whatever size the blocks are, and multiply their position by that. If the blocks are 4x4x4, multiply the position by 4. Note that I use y instead of z, since Roblox has Y as the up-axis, you have to use the Z-axis (or you get a grid that goes high up instead of flat on the ground).
Yes, well, if you want to do that, you need to set up your data structures in a way that you can efficiently fetch the data. I don’t understand what you want, but there’s probably an easier way to do it
What’s much, much faster than looping is indexing; it’s constant time. Set the keys of your blocks table as the block’s position and the values the blocks.
local position = Vector3.new(1, 1, 1)
Blocks[position] = block
-- Check if a position is occupied:
if Blocks[position] then
print("occupied!")
else
print("we can place here!")
end
-- Get the block from a position
local block = Blocks[position]
-- Remove a block in a given position
Blocks[position]:Destroy() -- Destroy the block instance
Blocks[position] = nil
Looping through a large table is and can be inefficient. I suggest that instead of storing your blocks in an array and searching through it, you can use a table as a dictionary where the keys are the positions of the blocks so you can quickly check if a block exists at a certain position without having to loop through the enter table.
local Blocks = {}
local function roundToStep(pos : Vector3)
return Vector3.new(math.floor(pos.X/3)*3+1.5,math.floor(pos.Y/3)*3+1.5,math.floor(pos.Z/3)*3+1.5)
end
function GridSystem.PlaceBlock(pos,color,material)
local roundedPos = roundToStep(pos)
local posKey = tostring(roundedPos) -- Convert the position to a string to use as a key
if Blocks[posKey] then
-- A block already exists at this position
return
end
local block = Instance.new("Part")
block.Parent = workspace.Blocks
block.Position = roundedPos
block.Size = Vector3.new(3,3,3)
block.Anchored = true
block.Color = color
block.Material = material
Blocks[posKey] = block -- Store the block in the table with the position as the key
end
function GridSystem.RemoveBlock(pos)
local roundedPos = roundToStep(pos)
local posKey = tostring(roundedPos) -- Convert the position to a string to use as a key
local block = Blocks[posKey]
if block then
block:Destroy()
Blocks[posKey] = nil -- Remove the block from the table
end
end
When you want to place a block, you first check if a block already exists at that position by checking if Blocks[posKey] is not nil. If a block doesn’t exist, you can create a new block and store it in the table with the position as the key. This is so when you want to remove a block, it just destroys the block and removes it from the table.
I have another issue related to that one. So i have a part that is the map ( the ground) and i try to index the entire ground as taken region. i have looped the entire size of the map but it somehow places cubes inside the map parts.
this is the code for that
for i,v in pairs(workspace.Map:GetChildren()) do
for x= -v.Size.X / 2 ,v.Size.X / 2-3,3 do
for y= -v.Size.Y / 2 ,v.Size.Y / 2-3,3 do
for z= -v.Size.Z / 2 ,v.Size.Z / 2-3,3 do
table.insert(Blocks,roundToStep(v.Position+Vector3.new(x,y,z)))
end
end
end
end
why it still places blocks inside the map parts that are taken?
Edit: for anyone in the future with this problem, i fixed it by changing the function to:
for i,v in pairs(workspace.Map:GetChildren()) do
for x= -v.Size.X / 2 ,v.Size.X / 2-3,3 do
for y= -v.Size.Y / 2 ,v.Size.Y / 2-3,3 do
for z= -v.Size.Z / 2 ,v.Size.Z / 2-3,3 do
Blocks[roundToStep(v.Position+Vector3.new(x,y,z))] = v
end
end
end
end