Correctly Performing Spatial Queries

I highly recommend marking your reply as the solution or updating your post with your new question.

Also, spatial queries do not “update”. Querying an area only finds everything in the provided area at the moment you query it. If you want to track the changes in that area then you must query it repeatedly over time and track the changes yourself by comparing the new results with past results.

If you believe RunService.Heartbeat too little time then you can use a loop with a custom delay using task.wait(delayTime). However, if you want to know the results immediately then it’s best to connect it to RunService.Heartbeat. I have used the spatial query API before and was worried about the same thing. However, after monitoring the script performance I can safely say that it is not a big concern. It does, however, depend on your usage. If your game will be querying a lot then you will need to find/create performance optimizations.

Here’s an example for tracking the changes in an area over time:

local RunService = game:GetService("RunService") local areaCache = {} -- an array containing the the areas we are tracking local function trackArea(location, size, params)	local area = {}	area.CFrame = location	area.Size = size	area.CurrentQuery = {} -- the returned value of the most recent query	area.PreviousQuery = {} -- the returned value of the previous query	area.Params = params -- params do not have to be provided	table.insert(areaCache, area) end local find = table.find RunService.Heartbeat:Connect(function() -- the function that is run every frame and checks the areas	for _,area in ipairs(areaCache) do	area.PreviousQuery = area.CurrentQuery -- update the previous query	area.CurrentQuery = workspace:GetPartBoundsInBox(area.CFrame, area.Size, area.Params) -- this can be any type of spatial query you want, whether it's in a part or radius. this is only for example purposes	local prev,cur = area.PreviousQuery,area.CurrentQuery	local maxLength = if #cur >= #prev then #cur else #prev	for i=1,maxLength do	local prevPart = prev[i]	local curPart = cur[i]	if prevPart and not find(cur, prevPart) then	print("Part Left Area: ",prevPart)	end	if curPart and not find(prev, curPart) then	print("Part Entered Area: ",curPart)	end	end	end end) 


If you don’t know much about optimizing your scripts and/or systems then you can use a pre-existing module for what you need. There are a few that are really good that you can use and have already been tested, improved, and optimized. I have provided their links below, in order of perceived usefulness to you. I have also provided a few other that use the spatial query API that you may find useful to use or learn from.

9 Likes