New RaycastParams Property, Deprecating Old Raycast Functions

We’ve added a new property to RaycastParams called CollisionGroup.
Parts in collision groups set to not collide with the passed CollisionGroup will be ignored by the raycast. If you don’t set this property, the raycast will assume the “Default” collision group as it did in the past.

If you are unfamiliar with RaycastParams, read the WorldRoot:Raycast documentation. It’s also outlined in this intro to raycasting tutorial. This is the only raycast function you should use in games going forward!

Collision groups functionality will not be added to FindPartOnRay, FindPartOnRayWithIgnoreList, or FindPartOnRayWithWhitelist. These are now :x: deprecated :x:

Why use this?

Using a collision group for raycasts is often easier than managing an ignore list table in code. You can set up collision group filtering in edit time, and parts can be assigned to specific groups when spawned rather than being inserted to a table.

How do I use this?

Here’s an example Collision Group configuration:


GunRaycast is configured to not collide with “Decor” and “Windows”, but still collides with “Players” and everything else. Players still collide with “Windows”, but not “Decor”. This means guns shoot through windows and decor, but still hit players. Players cannot go through windows, but they can go through decor.
In code, the RaycastParams can be defined as follows:

local myParams = RaycastParams.new()
myParams.CollisionGroup = "GunRaycast"

and the same RaycastParams object can be used for all gun raycasts.

workspace:Raycast(gunPosition, gunDirection, myParams)

Any parts spawned for effects when firing the gun for example, can simply be added to the “Decor” group when spawned:

local ps = game:GetService("PhysicsService")
local effectsPart = spawnGunEffectPart()
ps:SetPartCollisionGroup(effectsPart, "Decor")

That’s it! Feel free to ask questions or report issues here. Thanks!

159 Likes

Glad you’re moving forward with this, but I have to point out the silly nature of a RaycastResult being nil unless it hit an object. I don’t like this behaviour - is it intended?

16 Likes

Thanks! This will help a lot with developers and scripters. :+1:

2 Likes

This does make things difficult, but if you’re making a gun, then you can get a position from the max distance of the ray and it’s direction and create a beam from it. It was confusing at first, but it isn’t necessary to have it not always return nil.

(and from https://developer.roblox.com/en-us/articles/Raycasting, the returning of nil is intended)

5 Likes

Great! This will definitely help us developers!

(Off-Topic)Question: Why is this nearly a month old and we are not noticing it before now?

2 Likes

Because I saved the post as a draft a month ago and it wasn’t released until now lol

21 Likes

I’m in agreement if this. If the goal here is to make the transition easier for developers, then this behavior should be returned to the Raycast function. Yes it’s currently intended, but that does not mean it is not subject to or shouldn’t change.

12 Likes

Welp, this will be one hell of a switch. All of my games use FindPartOnRayWithIgnoreList ;(
I’ve never touched the newer raycast methods, but I’ll definitely try it out (and hopefully, I’ll like it :slight_smile: )

5 Likes

I love that raycasting is being worked on! These new API signatures will make things a lot more elegant.

I noticed that you folks switched to new enums/API but they still use non-inclusive language like “whitelist” and “blacklist”. Switching to these new signatures and deprecating the old ones would have been an opportunity to change this to e.g. “allowlist” and “denylist”, but that train has now passed. Is Roblox looking into using more inclusive language in new publicly exposed API?

18 Likes

Yea, so I wasn’t involved in designing the new Raycast API (just this new property), but it has been released for a while, and I know I at least wasn’t aware of the exclusivity of this language until a couple months ago.

I believe now there is an initiative being worked on to update language across all our API, and should be rolled out all at once.

13 Likes

So is this pretty much a blacklist but for collision groups instead of having a big table filled with objects? This is amazing!

2 Likes

Not sure how I feel about this. On the one hand, this is awesome being able to have it all simplified into one function. On the other hand, I did like the giant table method because I could run a for loop and add specific parts in some rays and different parts in others. Not sure how I really feel about the collision group but I’ll adapt.

Overall very excited to see this

3 Likes

There are unfortunately some use cases where it’s slightly harder to get what you want thanks to returning nil, but it’s the better behavior, as it forces you to actually think about how to correctly handle the case where nothing was hit: Some pieces of code just used the “hit” position before in cases where they really shouldn’t have been.

When considering the potential use cases, I found that the majority do want a branch, and I think that people will tend to write more correct code with the new API.

The goal of the raycast API is not to make raycasting easier to use for developers. The old API was easier to use, the problem was that it was not sustainable and was holding us back from adding very useful and highly requested features like this one. The cost of having that more powerful and flexible raycast is that it’s more complex to use.

Ideally people can write simple to use wrappers around the full Raycast API it if they don’t need all the power it provides, though I understand there’s not great ways to distribute / find such wrappers right now.

6 Likes

You can still do this! In fact, it will have exactly the same performance as before, the reflection cost just happens at the time when you assign the table into the RaycastParams object, rather than the point where you call the Raycast method.

And in the case where the black/whitelist does not have to change, you get better performance as it doesn’t have to be reflected an additional time.

9 Likes

This seems like a very bloated and ugly function. What if I want to raycast in such a way that everything is accounted for, regardless of collision groups? A use case for this would be in a plugin that renders the map from a top-down perspective. It seems like this new function does not provide a way for this, and therefore I would have to use the deprecated functions.

These functions should therefore not be deprecated, since there are still use cases which are not covered by the new parameters.

10 Likes

The behavior will be exactly the same as it was before in the case where the parameter is set to the default collision group, as Raycasts have always acted as though they were part of the default collision group.

In your top down perspective example, this gives you more flexability: You can create an explicit “world map” collision group to use for said Raycasts, and toggle it to have exactly the collidability that you want to filter what objects show up on the world map.

3 Likes

Is this true? I thought Workspace:FindPartOnRay had never accounted for collision groups in the past; so you’re saying that, before this update, if I called workspace:FindPartOnRay()..., and some part was in a collision group that was non-collidable with “Default”, it wouldn’t be accounted for with this call? Or do you mean just the WorldModel:Raycast function?

This sounds really sketchy. I would have to manually set the collision group of every part in the workspace, and hope that the user does not save and close their place before I complete the operation and set collision groups back.

4 Likes

Yeah, I’ve literally run into this myself. This update only adds functionality. I’m actually really glad they added this as I have some collision groups that collide with each other but not Default and I’ve never been able to use raycasts with them.

2 Likes

Or leave RaycastParams.CollisionGroup as Default, use RaycastParams.FilterDescendantsInstances and set RaycastParams.FilterType if you want to replicate the exact functionality of the old methods.

1 Like

All raycasting variants exposed to Lua have always only hit things which collide with the Default collision group. You can try it out for yourself if you don’t believe me, this change hasn’t touched the old raycasting functions at all, the behavior they have right now is what they’ve always had.

Well… yes, if you want to use collision groups then you will have to set collision groups on the relevant objects.