Hello there, its been quite some time since I first came across this thread, but I learned how to do this recently and figured I should share it!
I made a module that makes it as easy as this:
local movement = require(script.movement)
local start = part.Position
local to = Goal.Position
local angle = 45 --in degrees
local velocity = 25 --initial speed
local playlength = 2 --how long the movement tween plays for
movement.parabola(part,start,to,angle,velocity,playlength)
Where all you need to know is that the value for “velocity” is the speed it gets launched at from an “angle” value.
essentially simplifying the formulas that you see on the image.
And heres how that looks like:
parabolic_part.rbxm (4.8 KB)
The simplified version of how it works is that using the proyectile motion formulas we determine the Y position of the projectile in an instant in time “t”. And we calculate the flight time (time the projectile is in the air) in order to use it in a loop so it iterates until the current time >= flight time, which is when the projectile has reached its destination. Heres the module:
local ts = game:GetService('TweenService')
local module = {}
function module.parabola(object:BasePart,From:Vector3,To:Vector3,angle:number,velocity:number,playlength:number)
local args = {object,From,To,angle,velocity,playlength}
for i=1,#args do assert(args[i],'Err: Missing argument '..i) end
local t,g = 0,9.8 --time and gravity
-- Final and Starting positions
local XZf,XZo = Vector3.new(To.X,0,To.Z),Vector3.new(From.X,0,From.Z)
local Yf,Yo = To.Y,From.Y
--Calculating Velocities
local Voy = velocity*math.sin(math.rad(angle)) --Initial velocity in Y
local ft = (math.sqrt(2*g*Yo-2*g*Yf+Voy^2)+Voy)/g --calculating flight time / max air time
local Vxz = (XZf-XZo)/ft --Velocity in X and Z
--functions to get position with respect to time y(t) xz(t)
local ypos = function(t) return Yo + Voy*t - 1/2*g*t^2 end
local xzpos = function(t) return XZo + Vxz*t end
local V3pos = function(t) --return position in a vector3
local xz = xzpos(t)
local y = ypos(t)
return Vector3.new(xz.X,y,xz.Z)
end
--stuff for tweening / animating, for custom playbackspeed.
local tinfo = TweenInfo.new(playlength,Enum.EasingStyle.Linear)
local twt = Instance.new('NumberValue',script)
local tween = ts:Create(twt,tinfo,{Value=ft})
local run = true
local cn
tween:Play()
cn=tween.Completed:Connect(function() cn:Disconnect() run = false end)
while task.wait() and run do --position loop
t = twt.Value
object.CFrame = CFrame.new(V3pos(t),V3pos(t+.1))
end
twt:Destroy()
print('completed movement')
end
return module