Extra
Ray has a Unit property. If you end up having to use such property, its direction property is the exact same as the normal one. (ray.Unit.Direction = ray.Direction)
:ViewportPointToRay() does not accurately go where the mouse is. Better to use :ScreenpointToRay().
Mouse is superceded by UserInputService so while Mouse.Hit works, you will be at a disadvantage when wanting to implement things that UserInputService or ContextActionService have.
But it’ll take longer than just Mouse.Hit of course so you could use a module that acts similar but it’s not that complicated.
You get X, Y coordinate values which represent a 2D point on the screen (since your screen is just a flat 2D plane of space you’re looking through) then you can use :ViewportPointToRay() or :ScreenPointToRay() that accepts the X, Y parameters into it plus an optional depth parameter.
However, I believe depth moves the origin forward which we don’t want to have.
Though, the direction property gives a directional vector that is one stud long so we can multiply it to increase the distance/range. (500 is used here)
The RayParams is officially newer raycasting API so you might want to use it instead of the FindPartOnRay functions. You can also use the new :Raycast() function. The Ray object is still useful if you want to use its origin & direction.
local camera = workspace.CurrentCamera
local params = RaycastParams.new()
params.FilterDescendantsInstances = {} -- anything you want, for example the player's character, the ray filters through these
params.FilterType = Enum.RaycastFilterType.Exclude -- choose exclude or include
local function rayResult(x, y)
local unitRay = camera:ScreenPointToRay(x, y) -- :ViewportPointToRay() is another choice
return workspace:Raycast(unitRay.Origin, unitRay.Direction * 500, params) -- 500 is how far to raycast
end
-- rayResult will be a RaycastResult, link to API page below
Learn more here:
https://create.roblox.com/docs/reference/engine/classes/WorldRoot#Raycast
https://create.roblox.com/docs/reference/engine/datatypes/RaycastResult
To get x and y values for the function, use the function UserInputService:GetMouseLocation() for a Vector2 of the mouse position. However, this is only for mouse users.
For non-mouse users, get the position of an InputObject or a Vector2 argument from a ContextActionService binded function or UserInputService event connected function. (some mobile events receive a Vector2 argument instead of input object)
Example Scripts with above code
Example (mouse):
local mousePos = UserInputService:GetMouseLocation()
rayResult(mousePos.X, mousePos.Y)
Example (mouse & mobile supported):
local uis = game:GetService("UserInputService")
uis.InputEnded:Connect(function(input, gameProcessed) -- not exactly a click, but like the end of a mouse press or tap
if not gameProcessed then
local inputType = input.UserInputType
if inputType == Enum.UserInputType.Touch or inputType == Enum.UserInputType.MouseButton1 then
rayResult(input.Position.X, input.Position.Y)
end
end
end)
EDIT: Shortened answer for brevity. I actually googled my own answer once when I forgot how to do this stuff so I’m happy to see the many likes.