Okay so there’s a bit of a small thing I’ve sort of ran into and I’m not entirely sure how to make it optimal.
So let’s say I’ve got some weapon that needs to sway, or a object that constantly needs to tween to a new location, every frame, at the same speed.
I’m very familiar with lerping and tween service, but there’s just a few things I can’t seem to fully achieve with these methods of procedural animation or movement.
TweenService
So, I like TweenService. The only issue with it is that if you constantly have to tween something that has a new value every time then you end up constantly creating/destroying tweens and I feel like this negatively impacts performance if done for a lot of objects.
I also generally like to stick to my own way of designing systems which is trying to create/destroy as least objects as possible.
And tweens are reusable, but not if the goal post is constantly moving around.
Lerp
This might actually be my solution, but I’m not sure what kind of math to use to get the desired result.
I’ve tried this:
RunService.RenderStepped:Connect(function(delta)
part.CFrame = part.CFrame:Lerp(goal, delta)
end)
Now please don’t roast me for this, this probably is the “bad” way of doing it and I was trying random things at some point.
The problem with this approach is, it kiiinda works?
But caused said object to move slower the closer it is to it’s goal and also, it doesn’t quite reach it’s goal 100% ever, even if the goal is not moving.
This is like letting an ant walk on a rubber band that keeps infinitely stretching so the ant never makes it to the tip but does appear to get closer every step.
Whatever the heck this approach is.
Just imagine that this is in some RenderStepped loop.
local goal = {...} -- Imagine this is a constantly moving/changing vector, decomposed into a table for convenience.
local coords = {startVector.X, startVector.Y, startVector.Z}
for i = 1, 3 do
if coords[i] > goal[i] then
coords[i] -= stepSize * frameDelta
elseif coords[i] < goal[i] then
coords[i] += stepSize * frameDelta
end
end
local composedVector = Vector3.new(coords[1], coords[2], coords[3])
Now this would kinda work too?
Only issue is that if we get REALLY close to the goal vector and the distance is between our current position and goal position is smaller than the step size, we’ll over-step.
So I’ll have to write extra code, just to check if the distance between our current position and goal position is small enough to skip the whole interpolation process all together.
Which I was not sure of what the most optimal way to do this would be.
The code shown here above is also roughly how I programmed spring physics before (just add acceleration / deceleration to the code).
But the spring would never stop moving or jittering after it stopped bouncing because it kept over-stepping near it’s goal position.
So I had to write some clunky code to check if the speed / distance was small enough to just make the spring completely stop moving and that ended up looking weird too.
I cannot provide a lot of examples but I do know there’s plenty of things I need this sort of interpolation for.
And I’m looking for a way to make it fast, performant and dead-simple and keep the code very small.
I haven’t been doing a lot on my maths lately so I likely missed a method or simple formula for interpolating at constant-speed towards a constantly moving goal post without over-stepping.
The answer could be right in front of me or something very obvious and maybe I currently just don’t have the brain capacity to realize it or figure it out right away.