So i’m trying to make a suppression effect when a raycasted bullet comes near a player.

-- position is the head position from the player firing the bullet
local ray = Ray.new(position, direction * 100)
local distance = ray:Distance(character.Head.Position)
-- character is the player being suppressed

In this video, the shooter is shooting at a wall while the raycast comes near the standing player.
(minor sound warning)

The number that :Distance() returns is printed in the output. It increases as the shooter walks away. Isn’t it supposed to return the distance between the closest point on the ray to the Vector3 given (in this case character.Head.Position?)

In this video the shooter is shooting into the far distance while walking backwards to the player.

When the shooter’s back is turned to the other player, the number printed in output is what I assume to be the distance of the ray’s origin to the player’s head. But when they go on the other side of the standing player, the number changes drastically!

Is the function bugged, or am I just using it wrong?

While I haven’t used these functions myself when raycasting, I believe the function you want to use is Ray:ClosestPoint because that returns a vector3 that’s been projected onto the ray so that it’s within the ray’s line of sight. The wiki notes that the ray must be a unit ray for this function to work as intended. So I guess from this, I would use ClosestPoint and then check the distance between that point and the character’s head to determine suppression through subtraction and magnitude. Ray:Distance returns the distance between the ray’s origin and the closest point on the ray to the one you gave the function.

Your ray needs to be a unit ray for ClosestPoint to work correctly (Ray). Distance uses the same logic under the hood so I suspect the same is true for Distance.

These functions of Ray are ones I never use, simply because when I’m creating a Ray for a raycast, it’s almost never a unit ray. So I’d need to make another ray, and refence the API docs each time to remember what exactly these do. For me, it’s much simpler to just do the projection with Vector3 I already have (and so do you, in the form of your direction Vector3). When you already have the Ray, based on some scalar multiple of your direction vector, you can get the distance from the Ray to the Head with just a vector projection:

local headToRayDistance = (Ray.Origin + (head.Position - Ray.Origin):Dot(direction) * direction - head.Position).Magnitude

The first part, (Ray.Origin + (head.Position - Ray.Origin):Dot(direction) * direction, is the location of the closest point on the ray to the head, found by projecting the ray.origin-to-head vector onto the ray direction vector, and then adding it to the origin.

Yes, but .Unit isn’t really a property, it’s a function that returns a new Ray object, equivalent to doing Ray.new(ray.Origin, ray.Direction.Unit). And ray.Direction.Unit is also not a property So there are some allocations and extra square roots hidden there. But that’s not really why I don’t use it, I don’t use the helper functions because I find the code harder to read. If everything is right there in raw Vector3’s, I can see the exact calculation being done. If it’s all wrapped up in helper functions, it’s a lot less obvious at a glance; you basically need the API docs to translate the code. At the end of the day, it’s a personal preference, the calculation ends up the same.