So I have a script that, when I click, a part moves from it's position to the mouse.Hit.p position, but I also want it to be limited to a maximum distance, how would I recalculate the target position to a new point with the maximum distance in the same direction.
I recreated my situation below, copy and paste it in a new project. Put it in a LocalScript in StarterPack.
local m = game.Players.LocalPlayer:GetMouse() local p = Instance.new("Part", workspace) local v = Instance.new("BodyVelocity", p) local c p.Anchored = true local point wait() function getDir(vec) local lenSquared = vec.magnitude^2 local invSqrt = 1 / math.sqrt(lenSquared) return Vector3.new(vec.x * invSqrt, vec.y * invSqrt, vec.z * invSqrt) end function ShowPointer(target) local point = Instance.new("Part", game.Workspace) point.Name = "Point" point.Size = Vector3.new(1,1,1) point.CanCollide = false point.Anchored = true point.Position = target + Vector3.new(0,1,0) point.BrickColor = BrickColor.new(21) local mesh = Instance.new("BlockMesh", point) mesh.Scale = Vector3.new(0.3,1,0.3) return point end function Unweld() if p:FindFirstChild("Weld") then p.Weld:Destroy() end end function Weld(char) p.Anchored = false c = char local torso = c.Torso Unweld() local weld = Instance.new("Weld") weld.Part0 = p weld.Part1 = torso weld.Parent = p weld.C0 = CFrame.new(0,2,3) weld.C1 = CFrame.new() end function Move(target, maxDist) if c ~= game.Players.LocalPlayer.Character then return end p.Anchored = false Unweld() target = Vector3.new(target.X, p.Position.Y, target.Z) local dist = (target - p.Position).magnitude local dir = (target - p.Position).unit dist = math.min(dist,maxDist) target = dir*dist -- It works if I comment this line, but without the maxDist if point ~= nil then point:Destroy() end point = ShowPointer(target) p.BodyVelocity.velocity = getDir(dir) * 30.0 while dist > 0.5 and wait() do dist = (target - p.Position).magnitude end p.BodyVelocity.velocity = Vector3.new(0,-10,0) p.Anchored = true end function OnButton2Up() Move(m.Hit.p, 10) end m.Button2Up:connect(OnButton2Up) p.Touched:connect(function(hit) if hit.Parent:FindFirstChild("Humanoid") then Weld(hit.Parent) end end)
If anything is unclear, please leave a comment.
Any vector is a distance (a number) in a particular direction (a vector).
Since a scalar (number) multiplied by a direction vector is another vector (scaled by the scalar), a vector indicating direction is usually defined as length 1, so that dir * len
has length len
.
A vector of length 1 is called a unit vector. ROBLOX gives us a function to get the unit vector of any given vector through the .unit
property.
displacement = target - position -- The vector going from where we are (position) -- to where we are going [toward] (target) direction = displacement.unit distance = displacement.magnitude
We can get displacement
back by just multiplying direction
and distance
. If we want to make distance
at most maxDist
, though, we can limit it, for example, by using math.min
:
distance = math.min( distance, maxDist ) -- `distance` is now the smaller of `distance` and `maxDist`
And to get the new target point at most maxDist
away, we just multiply:
newTarget = direction * distance
One warning: If position
and target
are the same, the unit vector is undefined and may cause problems if you forget about that.
A simple check before doing too much with it is to make sure distance
is at least, say, 0.001
.