Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

[Solved] How do I calculate a point with a given distance and direction?

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.

3 comments

0

When I test it it seems to more or less behave correctly.

0

Well. The point is that, when I add dir*dist, the part still goes in the right direction, but look at the pointer. Also, keep in mind that it should only work when the part is welded to the player. I didn't add that to the script above, but that's the case in my full project.

0

Alright, I got it to work. After all it turned out to be that I have to add the p.Position to the outcome of dir*dist. Kind of obvious now that I think of it.

1 answer

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.

3 comments

0

Somehow the angle of the target changes when multiplying direction by distance.

0

I recreated my situation in the first post, you can copy and paste the full script in a new project. LocalScript in StarterPack, but I guess you know.

0

Could you help me out on this one? This really messes with my head.

This discussion is preserved as it was. New answers, comments, and votes are closed.