I’m trying to learn new ways to detect when the player is near stuff so I can let them interact with it and I discovered a method called spatial hashing which seems neat and is more efficient then what I used to do, however, it is quite confusing.
AFAIK it’s basically a grid of cells and you can put an object within a cell and then you can check for things within a cell (correct me if I’m wrong)
Here is my spatial hash class
function SpatialHash.new(cellSize)
local self = {}
local cellSize = cellSize
local spatialHash = {}
-- Calculate the hash key for the given position
local function getHashKey(position)
-- warn("Getting hash key")
local x = math.floor(position.X / cellSize)
local y = math.floor(position.Y / cellSize)
local z = math.floor(position.Z / cellSize)
return x.."_"..y.."_"..z
end
-- Calculate the cell coordinates for the given position
function self.getCellCoords(position)
-- warn("Getting cell coords")
local x = math.floor(position.X / cellSize)
local y = math.floor(position.Y / cellSize)
local z = math.floor(position.Z / cellSize)
return x, y, z
end
-- Add an object to the spatial hash at the given position
function self.addObject(object, position)
warn("Adding object:",object)
local key = getHashKey(position)
if not spatialHash[key] then
spatialHash[key] = {}
end
table.insert(spatialHash[key], object)
end
-- Get all objects in range of the given position
function self.getObjectsInRange(position, range)
local range = range / cellSize
local x, y, z = self.getCellCoords(position)
local objects = {}
for i = -range, range do
for j = -range, range do
for k = -range, range do
local key = (x + i) .. "_" .. (y + j) .. "_" .. (z + k)
if spatialHash[key] then
for _, object in ipairs(spatialHash[key]) do
table.insert(objects, object)
end
end
end
end
end
return objects
end
return self
end
And here is my code that uses it
local chest = workspace.Chest
local item = workspace.Item
local cellSize = 15
local range = 15
local spatialHash = SpatialHash.new(cellSize)
spatialHash.addObject(chest, chest.Position)
spatialHash.addObject(item, item.Position)
game:GetService("RunService").Stepped:Connect(function()
local x, y, z = spatialHash.getCellCoords(root.Position)
visualizationPart.Position = Vector3.new(x * cellSize, y * cellSize, z * cellSize)
end)
while true do
local objectsInRange = spatialHash.getObjectsInRange(root.Position, range)
for _, object in pairs(objectsInRange) do
print(object.Name .. " is within range of the player")
end
task.wait(1)
end
So the code does seem to work, however, I’m confused on how exactly the cell size and range is supposed to work I tried to make a visual part to try and help me understand, but I’m not sure if I did the math correctly because it looks a bit wonky.