A common approach in programming is to sacrifice memory for computation speed. If you store some things that you know you’ll need later, you won’t have to compute it every single time. If you choose good algorithms and data structures, you’ll have a much better chance of making something that works and works well.
One data structure that sounds like it might be handy in your case is a “2D table”. I usually implement that like so:
function mapGet(map, x, y)
if map[x] then
return map[x][y]
end
end
function mapSet(map, x, y, value)
map[x] = map[x] or {}
map[x][y] = value
end
Creating a new map is as simple as making a new table and just not using it for anything else. E.g.
local gridMap = {}
You can update the gridmap when an object is placed, something like this:
function placeObject(objectPrefab, gridX, gridY)
local oldObject = mapGet(gridMap, gridX, gridY)
if oldObject then
oldObject:Destroy()
end
local newObject = objectPrefab:Clone()
--probably set the object position
mapSet(gridMap, gridX, gridY, newObject)
return newObject
end
And you can check to see if a grid coordinate is occupied like this:
function isGridCoordOccupied(gridX, gridY)
return mapGet(gridMap, gridX, gridY) ~= nil
end
There’s some upfront work in updating the grid map. It’s not much when you’re just placing down single objects one at a time, but if you’re e.g. loading in a save game with 100s of placed objects all at once, it might take a second. It’s worth it though because we can check if a grid coordinate is occupied just with two table lookups, no complicated 3D math for collision detection or anything. It’s pretty much instant.