Upgraded, Improved, and Faster Raycasts

Hey devs,

We recently made some big internal upgrades to improve the performance of raycasts (ie WorldRoot:Raycast). We’ll be sharing the progress with you here along with some fun technical details.

Also, the max distance of raycasts has been raised from 5,000 → 15,000 studs!

Why Improve Raycasts?

Raycasts are the foundation for large chunks of our technical stack. Roblox uses them internally for Humanoid motion, BillboardGuis, Poppercam, ProximityPrompts, draggers, and other uses that need simple physical queries. Developers use them for collisions, bullets, tracers, suspensions, lasers, and other things that need a high degree of customization.

Time invested in making these faster massively benefits the platform with improvements such as more performant avatars, cameras, etc.

How?

We did a deep dive into the raycast systems and decided to go with a partial rewrite:

  • More optimal broadphase → midphase → narrowphase test ordering
  • Add ray-OBB test for parts to reduce how many times we fall through to more expensive narrowphase
  • New top-down broadphase traversal algorithm
  • Used hardware intrinsics (SIMD) to speed up the most common tests, e.g. ray-vs-box
  • Started caching part bounding boxes directly on each part
  • Improved the memory layout of physics parts for better spatial locality

The performance difference varies based on the workload. You can expect between a 10x improvement on long rays in huge maps with many large parts, to a 0x improvement on a completely empty map.

Rollout

These changes have been rolling out slowly over the past few months, with one of the bigger changes (the broadphase rewrite) having just released a few days ago. We have a bit of work remaining for accelerating some narrowphase routines, but the majority of the performance improvements should be visible in your maps right now!

We hope you like these improvements. Please share any feedback you have with the team here.

Thank you,

The Simulation Team

484 Likes

This topic was automatically opened after 5 minutes.

Cannot express how unbelievably important it is to have these raycast updates. Our experience uses raycasts to create hitboxes for our enemies; one boss fight enemy has over 3000 points to raycast from and does so every frame for a few seconds. Our solution is already relatively performant but if we can get that to be optimised even further, we’ll take it.

Hoping this paves the way for shapecasting soon, hopefully before the end of the year, but I’m down any time for them. :flushed:

101 Likes

Always welcome to see performance updates. After all, nothing beats increasing the performance of my games without even having to update them.

The increased range will also certainly prove useful, as these days we’re working with larger maps than ever before. Overall, a great update!

44 Likes

Yes, my empty game will finally be 0% faster! My players will now be able to get 0 extra frames while playing!

But really, great update can’t wait to use:

This was a limitation that annoyed me since other engines have no limit, it’s great to see this finally increased.

30 Likes

May I ask what a shape cast is exactly? Judging by the name Im thinking its a raycast but instead of a ray its a shape

7 Likes

Yeah, pretty much in the name. Think raycasting but you aren’t restricted to a line.

Shapecasting would be really good for our use case since we have mesh deformed enemies as well as enemies that perform large scale attacks. Since we don’t have shapecasts, we need to rely on other methods: several hundred or thousand raycast points, Touched (sort of ew to rely on physics for hitboxes), information from Bones to create raycast points and so on.

Our current method of slapping attachments all over the enemies isn’t sustainable in the long run and it’s slightly tedious to set up, especially with mesh deformed rigs. It’s also not completely consistent since some of our enemies are not mesh deformed, so we’ve had to make at minimum three different ways to raycast to catch all of our use cases appropriately.

You can find a few examples of shapecasting around: for example, if you check out SSBU frame data you can see that they have spherecasts in their animation frames which determine the hitbox:

Another example is Dark Souls 3. There is a tool that allows you to view the game’s models and animations and part of the animations is capsule casts showing where and when hitboxes are active:

image

Line raycasts just aren’t good for every occasion, plus it’d be great to raycast once over a certain area rather than a single line. It’d certainly help us to avoid this (mess):

image

That’s just a few casts on an old rig. It’s even worse on our newer enemies:

In non-technical terms: basically, think using parts and Touched for hitboxes but they’re raycasts and not actual parts. They also handle detection better because you don’t need to rely on the hitbox part to physically intersect another part to detect your hit.

Touched is decent-ish but not the most ideal solution for hitboxes: parts already intersecting will not get caught by Touched, needing you to use a workaround like connecting a blank Touched and use GetTouchingParts. This could all be simplified with an appropriate shapecast. Shapecasts would also remove physics simulation as a dependency for hitboxes.

63 Likes

The new stud limit changes everything, no but seriously I’ve been experimenting with Roblox raycasts and I just found the 5k stud limit to be annoying [as other engines had no or a way higher limit]

But yeah, other than that this update is just pretty good.

6 Likes

Wow I am just impresssed. This year I have been seeing a lot of performance improvements by the roblox physics team, with this rate of change we soon could have the massive physics based games I’ve dreamed of.

19 Likes

I tested my Roblox based ray tracer with the new optimizations to see how well it runs. I don’t have any of my old benchmark timings from a few months ago to compare to sadly.

Source:
image

Result:
image

Stats:
5 samples per pixel
Up to 2 bounces per pixel
Lighting rays: 640263
Shadow rays: 363396
Time to render: 21.436051368713 sec
(Edit: specified time unit)

My memory of my previous tests is a bit hazy, but I’m pretty sure that is quite a lot faster than it used to be. If anyone knows a way to test with the pre-optimization ray casts I can report back with a comparison to how it performed before.

There are a lot of lighting calculations going on in the script too so it isn’t 100% ray cast performance, but the ray casts are a significant portion of it.

27 Likes

I’ve went through a ton of issues with lower-end phones lagging in some games. Updates that make the game run faster are really “Powering Imagination”, as this will push the limits further. I love updates like this.

I wonder if this will also make RayCasts on a bunch of MeshParts with PreciseConvexDecomposition CollisionFidelity faster.

9 Likes

Whatever you do, if it is related to performance improvements then it’s very welcome!

6 Likes

These CPU/RAM rearrangements are a big and appreciated difference behind the scenes. Thanks for providing more power to back-end programmers!

5 Likes

I need this so bad for my fighting game lol. Currently all “hitboxes” are just a ray from the humanoid root part forward however many studs the attack is. This causes issues when it comes to hitting enemies when you aren’t directly facing them. I completely support this idea

5 Likes

Shapecasts are definitely on our radar :slightly_smiling_face:

93 Likes

Out of curiosity, if you were to implement shapecasts, how much faster do you think they would be compared to a luau implementation?

8 Likes

Been advocating for shapecasts for 4 years now… One day the dream will become reality, until then we cast tens of hundreds of rays at once.

3 Likes

Shapecasts, at least, Sphere (sometimes called a capsule cast, is basically a raycast with a radius, typically as two points and a radius, and its like two spheres and a cylinder), Box (like Region3s but they can be rotated and aren’t fixed to 4x4x4 voxels), and via part bounds are on the roadmap and are being worked on in the engine:

GetPartBoundsInRadius wouldn’t be a typical spherecast (its like a spherecast with both points at the same exact position, not sure if that’s a communication issue or intended), but, the typical behaviour could be recreated with two of those calls and a GetPartsInPart call. Additionally, I think GetPartBoundsInRadius/Box is actually meant to be GetPartsInRadius/Box

But, all of that will hopefully be worked out by the time it all releases. (@subcritical dunno if you know anything about that, or if that should be noted)

Well, technically there are no luau implementations. You would need access to collision geometry. However, the most common approach is to use :GetTouchingParts() which is typically very slow, and relies on CanCollide/collision group info unless a Touched event is connected.

It’s hard to really give a good benchmark on this without proper data on my part, but, connecting a call to this on Heartbeat for a complex part resulted in very poor performance, somewhere around maybe 20 or 30 milliseconds each, which, was getting me about 30 frames (normally I sat closer to 150 in the game I was testing this in)

12 Likes

Does this mean BasePart.CanQuery will be coming soon as well?

(Iirc this toggle means Raycast can / can’t hit the BasePart)

unless it’s already been enabled? I don’t remember that

4 Likes

Ray casting is used a lot in Roblox, but I was reluctant to do it befause of the lag on slow computers due to performance issues, but I think this update is very interesting and good! and I wish there was a performance update to the gravitational physics bullet system(continuous raycasting method with render stepped) I’m using! Thanks to Roblox.

1 Like