Roblox equivalent to unity's Vector3.MoveTowards

i am porting some code from unity to roblox, and i dont know how i would port some code that uses all 3 arguments of Vector3.MoveTowards Unity - Scripting API: Vector3.MoveTowards

what would be ROBLOX’s equivalent to this?

1 Like

If you are moving a part, you’ll most likely have to use TweenService or :Lerp() function (linear interpolation and for-looop) to smoothly transform coordinate frames. If you are moving a player or non-player character, it usually contains a humanoid, so you can use humanoid:MoveTo(), which is part of PathfindingService.

:Lerp() uses a percentage though unlike vector3.movetowards, what should i do about that?

This is a post I wrote some time ago in which I briefly compare “tweening” and “lerping”.

You can also find example code involving both options. I definitely recommend tweens. In a nutshell, we are changing alpha value and gradually moving the part, although not as smoothly as when working with tweens.

That Unity function only mathematically moves a point along a vector. So the Roblox equivalent is:

function vector3MoveTowards(point, targetPoint, delta)
	return (point + (targetPoint - point).unit * delta)
end
3 Likes

i am sometimes getting NAN when using this function, is that supposed to happen?

You can either use the PathFindingService, you can use humanoid:MoveTo(), or you can use TweenService.

That means the values you are passing it are having issues. Debug (print out) your values when NaN happens.

This was helpful to me but is still a little off I think. Because in Unity Vector3.MoveTowards also specifies the max allowable distance to travel.

A Roblox function would need to pass in point, targetPoint, delta, AND maxDistance.

With the solution you provided, we are indeed moving from point to targetPoint, but the distance traveled is always a unit vector multiplied by delta. In other words we’re stuck traveling one unit per second no matter what.

I’m still working it out, and I will edit this post when I have a solution.

Edit: Haven’t tested it yet, but this is what I came up with.

local function v3MoveTo(point, targetPoint, dT, maxDPS)	
	local movedV3 = (point + (targetPoint - point).unit * dT * maxDPS )
	if (movedV3 - point).Magnitude > (targetPoint - point).Magnitude then
		return targetPoint
	else
		return movedV3
	end	
end

dT is deltaTime.

maxDPS stands for max distance per second (since it will be multiplied by delta time which is a fraction of a second.) This allows for your move towards to be less than or greater than one unit. I also added this because it eliminates the confusion related to multiplying “maxDistanceDelta” with “Time.deltaTime”. (In retrospect the code by MrNicNac was fine provided that you multiply “delta” with a max distance number. But in any case, my version makes it so that you don’t overshoot the targetPoint)

The .Unit of a zero-length vector is undefined, you need to make sure you don’t pass this function a zero vector.

Lol I JUST implemented this and ran into that problem. Here is the new code. Looks a little different, but now it checks if point == to targetpoint and then it returns point so that targetPoint-point is never equal to (0,0,0) which avoids the (0,0,0).unit problem

local function MoveTowards(point, targetPoint, dT, maxDPS)
	if point == targetPoint then
		return point
	else
		local movedV3 = (point + (targetPoint - point).unit * dT * maxDPS)
		if (movedV3 - point).Magnitude > (targetPoint - point).Magnitude then
			return targetPoint
		else
			return movedV3
		end	
	end
end

Here’s my implementation of it, works perfectly:

  • delta: the amount of time that has passed since the last frame
  • currentPos: the current position of the Vector3
  • targetPos: the position to move towards
  • speed: the speed at which to move towards the target
function moveTowards(delta: number, currentPos: Vector3, targetPos: Vector3, speed: number): Vector3
    local direction = (targetPos - currentPos).Unit
    local distance = speed * delta
    local newPosition = currentPos + direction * distance

    -- If the new position has overshot the target, return the target position
    if (targetPos - newPosition):Dot(direction) < 0 then
        return targetPos
    end

    return newPosition
end

Here’s how you can use it, in a localscript:

-- Define the Part and Target Position
local part: BasePart = game.Workspace.Part -- replace with your part
local targetPosition: Vector3 = Vector3.new(10, 5, 0) -- replace with your target position

-- Define the Speed and DeltaTime variables
local speed: number = 5

-- Connect to the RenderStepped event
game:GetService("RunService").RenderStepped:Connect(function(deltaTime number)
    -- Move the Part towards the Target Position using the MoveTowards function
    part.Position = moveTowards(part.Position, targetPosition, speed, deltaTime)
end)

Did this script work for you?

  • Yes
  • No

0 voters