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.