Roblox Archer: Ranged-based operations sped up using a Binary Search Tree

I’m sure a lot of you can use this utility, so I open sourced it.

Let’s imagine you are trying to make a “fire spreading script”. The most simple, but also most naive way, is to do something like this:

  • Find a part which is on fire
  • Loop over all parts in Workspace, check if it’s close, and if so, light it (or any temperature-whatever based operation)

However, this scales really badly with the amount of Instances to check. This algorithm will be very slow.

A logical “fix” for this is to split up the Workspace into areas. If you check within a range of 20, and you have a box with instances which has a size of 40 studs, (and the “range sphere” fits in this box), then you only have to check for Instances within this box.

Also, if the sphere “overlaps” another box, you should check in that box. However, as you see, you also make sure that you “skip” a lot of Instances to check. Range operations like getting magnitudes are intensive operations, so they should be avoided.

Splitting up a group of instances is called a ‘binary search tree’ - (it’s actually a data structure). It’s easy to make. However, we all like to spend time on “fun” things, like playing with these trees. I just created this module - with documentation - and you can download it from github.

The repo includes a test place which simulates fire spreading. This is also the place I used to tweak some settings. A small overview of this place (don’t open it for the visuals!)

-> Spawn ~4096 bricks.
-> Load them into the Archer
-> Run Archer

Watch how the fire spreads (brick sizes indicate tempreature, the awesome visuals include color changing - i disabled fire particles to not fry the GPU for 4096 particle spawn). After that, upgrade Archers box range to a huge value, so the “naive” approach is simulated. Watch how the fire spreads much more slow.

I need to tweak some things though, but it’s useable now.

For a moment I was thinking you actually made an arching place using this or something.

Nonetheless, this is pretty cool.

[quote] For a moment I was thinking you actually made an arching place using this or something.

Nonetheless, this is pretty cool. [/quote]

my “marketing strategy” is awful.

It’s fun to code like this though. I have “targets” which are put in a “tree”. And then I let my Archer “fire” some “jobs”. I just took hipster coding to a whole new level :uhhh:

Thanks. This is awesome. I’ve submitted a few issues and pull requests on githubs.

[list]
[] https://github.com/jobro13/Roblox-Archer/issues
[
] https://github.com/jobro13/Roblox-Archer/pull/1
[*] I would also like to request the API be changed from Archer:New() to Archer.new() as is standard for most ROBLOX libraries.
[/list]

Oh neat. I could actually use this in my current project for grass rendering and improved fire spreading. Right now I just travel along the parts returned by BasePart:GetConnectedParts() for fire and break grass up into random clusters. I might rework them the work of this.

[quote] Thanks. This is awesome. I’ve submitted a few issues and pull requests on githubs.

[list]
[] https://github.com/jobro13/Roblox-Archer/issues
[
] https://github.com/jobro13/Roblox-Archer/pull/1
[*] I would also like to request the API be changed from Archer:New() to Archer.new() as is standard for most ROBLOX libraries.
[/list] [/quote]

Thanks. Read my comments on your pull request and issue, please :wink:

I guess this can be used, if :GetConnectedParts() is a static table. If you keep welding things, this will change, and I don’t think such data structure is suitable for this.

Also, I want to point out that this approach looks (to me) pretty “on the double”. I am sure that ROBLOX uses a kind of data structure for it’s physics. However, if you try to use the Region3 functions for such approach, you will find that they are incredibly slow. I don’t know why this happens. The problem is now that we are storing a data structure on both the Lua and the C side of ROBLOX. That looks like a waste of memory to me.

ROBLOX uses a quad tree for raycasting and physics that is broken up into regions, according to zeuxcg, IIRC. I know it’s optimized, and I doubt we can get better raycasting performance Lua side, the same may go for :GetConnectedParts() since it is precalculated

And yeah, I don’t think memory efficiency is a selling point for ROBLOX (or at least, my ROBLOX game), right now.

[quote] ROBLOX uses a quad tree for raycasting and physics that is broken up into regions, according to zeuxcg, IIRC. I know it’s optimized, and I doubt we can get better raycasting performance Lua side, the same may go for :GetConnectedParts() since it is precalculated

And yeah, I don’t think memory efficiency is a selling point for ROBLOX (or at least, my ROBLOX game), right now. [/quote]

Well, if we could have Lua access from it (I don’t even care if it’s an ugly API) then that would help, as I’m now clogging Lua’s side with a lot of tables, which is also stored on the C-side (in another format).

[quote] ROBLOX uses a quad tree for raycasting and physics that is broken up into regions, according to zeuxcg, IIRC. I know it’s optimized, and I doubt we can get better raycasting performance Lua side, the same may go for :GetConnectedParts() since it is precalculated

And yeah, I don’t think memory efficiency is a selling point for ROBLOX (or at least, my ROBLOX game), right now. [/quote]

Well, if we could have Lua access from it (I don’t even care if it’s an ugly API) then that would help, as I’m now clogging Lua’s side with a lot of tables, which is also stored on the C-side (in another format).[/quote]

That’d work out pretty badly if ROBLOX ever wants to migrate to another physics engine.

[quote] [quote=“Quenty” post=161917]ROBLOX uses a quad tree for raycasting and physics that is broken up into regions, according to zeuxcg, IIRC. I know it’s optimized, and I doubt we can get better raycasting performance Lua side, the same may go for :GetConnectedParts() since it is precalculated

And yeah, I don’t think memory efficiency is a selling point for ROBLOX (or at least, my ROBLOX game), right now. [/quote]

Well, if we could have Lua access from it (I don’t even care if it’s an ugly API) then that would help, as I’m now clogging Lua’s side with a lot of tables, which is also stored on the C-side (in another format).[/quote]

That’d work out pretty badly if ROBLOX ever wants to migrate to another physics engine.[/quote]

In that case, an interface to it. The actual structure doesn’t matter, the interface just provides general functions for it.