Raycasting Basics
This article will teach you how to use the method FindPartOnRay. If you want a practical application for it and not just a document that shows how to use it and what each part does, I suggest the article How to Make a Raycasting Lasergun. Now, let's get started.
The Basics
As an introduction to raycasting, you'll need to learn how to use the FindPartOnRay method. It takes two arguments, ray</syntaxhighlight> and
ignoreDescendantsInstance
The former is a Ray, while the latter is any Instance The second argument is optional, so I'll cover raycasting with only the first argument at first, and later with the second argument. FindPartOnRay returns two values,
object
and
position
The former is any BasePart hit by the ray, and the latter is the Vector3 position where the ray hit
object
If the ray doesn't hit any object,
object
will be nil, and Position will be
ray.Origin + ray.Direction
How to use FindPartOnRay
Let's take a look at the following code:
local ray = Ray.new(
Vector3.new(5, 10, 13),
Vector3.new(0, 5, 0)
)
local part, endPoint = Workspace:FindPartOnRay(ray)
That's the basis of how to use the FindPartOnRay method. The Ray constructor takes two arguments, and the second one is different than the one described on the Ray page. The first is the start point of the Ray in world space. The second argument is the end point in relation to the start point. So, in this case, it would create a Ray starting at {5, 10, 13} and ending 5 studs above it. You can also think of this as the length vector, as it is how long the ray is. On the Ray page, the second argument is described as being the direction of the Ray, however, with the FindPartOnRay method, this is not the case. You can use it like that if you would like to use a unit vector as a direction, you'd simply have to multiply the vector by 999 (the max distance).
As described before, the method will return nil for the first argument if it doesn't hit anything. If you don't take this into consideration while writing code and you need the BasePart that was hit, you will get errors in your code. We can check if it hit an object simply like this:
if part then
--Do stuff with the part
end
Since Lua evaluates everything except nil or false as true, we can simply input the part as the condition. That code will prevent errors that would arise from trying to reference the part if it didn't exist.
Before I briefly mentioned ray length. The max length of the ray is 1000, so you must keep this in mind while casting. If you need a ray longer than this, you can cast one ray, check if it hit anything, and if not, cast another ray starting at the end point of the previous one and continue on. Another note about length is that parts will not be checked outside of the length. Collisions will be tested only between the two points determined by the arguments you supply the ray.
ignoreDescendantsInstance
ignoreDescendantsInstance</syntaxhighlight> is the second argument that FindPartOnRay takes. Its use is simple: pass it anything that is an instance and it will ignore it and any descendants of it, as well as those descendants' descendants, and so on. This is very useful if there are parts you want to exclude in your collision check. However, you cannot pass a table in, and it doesn't accept multiple arguments for IgnoreDescendantsInstance, so if there is a group of parts you don't want to check, they should be temporarily grouped into a model, and then you should pass that model to IgnoreDescendantsInstance argument.
Final Notes
FindPartOnRay is an amazing method, however, it is not always the most useful or efficient thing you could use. If you say, "Oh, hey, this is really easy to use, I'm going to use it whenever possible," I highly suggest you think twice every time you want to use it to see if there's a better way. If you need to check if there is a part in the way of two points, go ahead and use FindPartOnRay. If you need to find all parts within the radius of a certain point, there's probably a better and easier way to do it with Magnitude or another method, but this article isn't about explaining that.
See Also