I just finished making a grapple hook and it is pretty nice, but it’s really hard to aim when your speed is very fast. I was wondering how I can get the closest point to the mouse, but I have no idea how to do it.
local function ClosestPointOnPart(Part:BasePart,Point:Vector3)
local ObjectSpace = Part.CFrame:PointToObjectSpace(Point)
local Size = Part.Size / 2
return Part.CFrame * Vector3.new(
math.clamp(ObjectSpace.X,Part.Size.X / -2,Part.Size.X / 2),
math.clamp(ObjectSpace.Y,Part.Size.Y / -2,Part.Size.Y / 2),
math.clamp(ObjectSpace.Z,Part.Size.Z / -2,Part.Size.Z / 2)
)
end
When you point below it, I would expect it to get the top because from my view, the top would be the closest point, but it returned the bottom position. It also only works for one part.
You can combine the Workspace and the Workspace to locate the spot on a part that is closest to the mouse. The Camera and the CurrentCamera object. technique of ViewportPointToRay. By doing so, you’ll be able to translate the mouse position from screen space to real-world space and then determine where the ray and the portion cross.
Here is some sample code that shows how to accomplish this:
--// --> Find the camera and mouse position
local camera = game.Workspace.CurrentCamera
local mousePosition = game:GetService("UserInputService"):GetMouseLocation()
--// --> Convert the mouse position to a ray in world space
local ray = camera:ViewportPointToRay(mousePosition.X, mousePosition.Y)
--// --> Find the intersection point between the ray and the part
local part = script.Parent
local closestPoint = ray.Origin + ray.Direction * ray.Direction:Dot(part.Position - ray.Origin)
print(closestPoint)
The point on the component (script.Parent) that is closest to the mouse position will be printed by this code. This location can serve as the grapple hook’s target position.
You can cycle through all the parts and compare the distance between the ray and the positions of each part to determine which point on each part is the closest. The portion nearest to the mouse will be the one with the shortest distance.
Here is some sample code that shows how to accomplish this:
--// --> Find the camera and mouse position
local camera = game.Workspace.CurrentCamera
local mousePosition = game:GetService("UserInputService"):GetMouseLocation()
--// --> Convert the mouse position to a ray in world space
local ray = camera:ViewportPointToRay(mousePosition.X, mousePosition.Y)
--// --> Find the part closest to the mouse
local closestPart = nil
local closestDistance = math.huge
for _, part in pairs(game.Workspace:GetDescendants()) do
if part:IsA("BasePart") then
local distance = (part.Position - ray.Origin):Dot(ray.Direction)
if distance < closestDistance then
closestPart = part
closestDistance = distance
end
end
end
--// --> Find the closest point on the closest part
local closestPoint = ray.Origin + ray.Direction * closestDistance
print(closestPoint)
This code will locate the component that is closest to the mouse before locating the component’s closest point. This location can serve as the grapple hook’s target position.
Sorry, but this didn’t really work. (but it definitely looks cool!)
local RunService = game:GetService('RunService')
local UIS = game:GetService('UserInputService')
local Camera = game.Workspace.CurrentCamera
RunService.RenderStepped:Connect(function()
local Part = workspace.Part
local Pos = UIS:GetMouseLocation()
local Result = Camera:ViewportPointToRay(Pos.X,Pos.Y)
local closestPoint = Result.Origin + Result.Direction * Result.Direction:Dot(Part.Position - Result.Origin)
workspace.Point.Position = closestPoint
end)
Just a side note: If you are wondering why I am not using a raycast, it is because I want to be able to grapple objects, and I don’t want to add friction when I do this.
I’m not sure, but I think you’re talking about the closest point on a surface? If so, I’m pretty sure that this is the algorithm:
Create a plane from the surface’s normal and the position of the mouse. Then, find the intersection of this plane and the surface.
I hope this helps.