I eventually figured out OverlapParams are formatted the same way as Raycasts.
E.g.,
local Params = OverlapParams.new()
Params.MaxParts = 5
workspace:GetPartsInPart(part, Params)
I still haven’t found a better method for checking updated spatial queries. I currently check every frame via RunService.Heartbeat:Wait() which seems excessive.
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.