Hello dev forum,
I wanted to find out of combining CollectionService and spatial queries was useful.
Here is the idea:
Lets say you have a collection of BaseParts / Models tagged with the tag objects, scattered around your map. Instead of running spatial queries on the entire collection of objects, you would “zone tag” each object each interval t. What i mean by that is, you will be updating a special tag associated to each object, depending on their position and a zone size variable. The objects position will then be grid-snapped (with the grid size being the zone size) and the tag will be updated. (a tag can look like “_zone130/0/130”). This process will repeat until you decide to stop it, every interval t.
This whole thing sounded really stupid but i decided to put it to the test to see if it is of any use
Experiments
Exp. number 1:
- Query method: GetPartBoundsInBox()
- Query Size: 50 x 10 x 50
- Map size: (2048,8,2048) (Standard baseplate)
- Total parts queried: 6K
- Zone Size: 50
Results:
---------------------------------1M queries--------100K queries
Without zone tagging : 32 seconds--------3.2 seconds
With zone tagging : 18 seconds-------------1.4 seconds
Increasing the number of parts
Exp. number 2:
- Query method: GetPartBoundsInBox()
- Query Size: 50 x 10 x 50
- Map size: (2048,8,2048) (Standard baseplate)
- Total parts queried: 40K
- Zone Size: 50
Results:
---------------------------------10K queries--------100K queries
Without zone tagging : 7.3 seconds--------74 seconds
With zone tagging : 0.7 seconds-------------9.8 seconds
According to the documentation GetPartBoundsInBox() considers part Size as the object bounds instead of its actual geometry, which makes it quicker and more efficient. I decided to do the next experiment with GetPartsInPart() method, which considers part geometry
(note: i only tested with block parts which might have been a mistake)
(screenshot: sort fo like a worst case scenario, a baseplate jampacked with parts)
Exp. number 3:
- Query method: GetPartsInPart()
- Query Size: 50 x 10 x 50
- Map size: (2048,8,2048) (Standard baseplate)
- Total parts queried: 40K
- Zone Size: 50
Results:
---------------------------------10K queries--------200K queries
Without zone tagging : 6.3 seconds--------136 seconds
With zone tagging : 0.5 seconds-------------18 seconds
Honestly, dont know what to really make of this one, apart from the 200K query times being approx. double the 100k query times of the last experiment which makes sense i guess
For this next experiment, i increased the map size to 10 000 x 10 000
Exp. number 4:
- Query method: GetPartBoundsInBox()
- Query Size: 50 x 10 x 50
- Map size: (10 000, 8, 10 000)
- Total parts queried: 40K
- Zone Size: 50
Results:
---------------------------------100K queries
Without zone tagging : 1.5 seconds
With zone tagging : 0.4 seconds
Final experiment: increasing the Query size
Exp. number 5:
- Query method: GetPartBoundsInBox()
- Query Size: 200 x 10 x 200
- Map size: (10 000, 8, 10 000)
- Total parts queried: 40K
- Zone Size: 50
Results:
---------------------------------100K queries
Without zone tagging : 12.6 seconds
With zone tagging : 2.9 seconds
I also tried increasing/decreasing the zone size (10 - 400) but that didnt impact the results at all
Teleporting parts around randomly and tweening didnt have any impact either
Usage
This system can not be used for precise zone detection (player entering a zone triggers, area effets,…) unless you decrease the tag update interval i guess (still dont think its a good idea)
But for “grabbing” parts in a certain area it can work well.
I have attached the module below. Here are the methods:
init(trackertag : string, zonesize : number, updateinterval : number)
All of the objects tagged with trackertag will be added to the array. Instances added / removed later will also be accounted for.
addobject(object) removeobject(object)
Manually add / remove a object to the array
start() quit()
*start / stop the zone tag update loop
getzonetag(position : Vector3) → string
PositionFromTag(tag : string) → Vector3
Can be used for BaseParts or Models!
ZoneTagging.lua (4.2 KB)