Hello devs,
I am making a game where you can send ships from one planet to another. I created a block, which serves as a midpoint for the ships and coordinates them around it. I decided to use lerping to move the midpoint from one place to another.
As shown in the video, whenever I move multiple midpoints at once, they all get to the same location at the same time, despite one planet being distinctly farther than the other. This is because lerping uses percentages instead of actual distances for movement.
My code
local startcf = node.Body.CFrame
local attackcf = attacknode.Body.CFrame
local distance = (attacknode.Body.Position - node.Body.Position).Magnitude
local spawnpercent = node:GetAttribute("SpawnRadius")/distance
task.spawn(function()
for i = 0,1,0.0005 do
midpoint.CFrame = midpoint.CFrame:Lerp(attackcf, i)
task.wait()
end
midpoint:Destroy()
end)
I’m just asking how I would instead use set distance instead of percent in lerping, so that all midpoints move the exact same speed regardless of distance spawned away from the planet.
You can calculate the time it should take to reach the destination
local startcf = node.Body.CFrame
local attackcf = attacknode.Body.CFrame
local distance = (attacknode.Body.Position - node.Body.Position).Magnitude
local SPEED = 12 -- Studs/s
task.spawn(function()
local lerpTime = distance/SPEED -- Time it takes to reach the end
local startTime = os.clock() -- returns cpu time
while true do
local alpha = (os.clock() - startTime)/lerpTime -- returns 0 after 0 seconds, and 1 after lerpTime amount of seconds
-- Here you can use TweenService:GetValue() to make it non-linear
clampedAlpha = math.min(alpha,1) -- If alpha is bigger then 1, clamp it to 1
midpoint.CFrame = startcf:Lerp(attackcf, clampedAlpha)
if alpha > 1 then break end
task.wait() -- This could be replaced with RunService.RenderStepped:Wait() to make it smoother
end
midpoint:Destroy()
end)
This approach is a bit different, instead of doing a predefined amount of steps, it does one step every frame, and uses tick to determine where along the line it should be. This approach means you can precisely control the speed, and time it takes for it to reach the target, and isn’t affected by lag or fps unlockers
Another thing you can do is use TweenService:GetValue(alpha,easingStyle,easingDirection), which basically transforms the alpha given to a new alpha value that follows one of the tweening functions, to, for example, make it move faster at the start and slower as it approaches the destination
I did not test my code so I might have gotten something wrong, although I am confident I got it right lol
I switched to Tweening, and it works well. However, the larger distance goes even faster than the closer distance.
My code:
--Move Midpoint--
local distance = (attacknode.Body.Position - node.Body.Position).Magnitude
local traveltime = 1000/distance
local tweeninfo = TweenInfo.new(
traveltime,
Enum.EasingStyle.Linear,
Enum.EasingDirection.In,
0,
false,
0
local movement = ts:Create(
midpoint,
tweeninfo,
{Position = attackpos}
)
movement:Play()
This reverse in the movement speed definitely has to do with my math though. If I’m dividing by the distance, the speed is always going to be shorter the longer the distance. I just don’t know how to reverse it…
Yeah, what you want to do is have a Speed variable, studs/s and a distance. To get the time it should take, it’s not very complicated
Lets say you have 30 studs, with a speed of 5 stud per second
if you divide 30 by 5 you get the time, which would be 6 seconds
It works! Everything moves at the same speed. My problem was that I reversed the division, creating an inconsistent dividend. By using distance as the dividend makes the movement fully independent from distance.
Thank you for your time.