Creating a smooth arc projectile using bezier curves

Hi want to create a smooth arc projectile using bezier curves.
I have an idea of using body velocities or positions with tweens but can’t seem to figure it out.

function lerp(a, b, c)
return a + (b - a) * c
end

function CubicBezier(t, p0, p1, p2, p3)
local l1 = lerp(p0, p1, t)
local l2 = lerp(p1, p2, t)
local l3 = lerp(p2, p3, t)
local a = lerp(l1, l2, t)
local b = lerp(l2, l3, t)
local cubic = lerp(a, b, t)

return cubic

end

for t = 0, 1, .001 do
BezierPosition = CubicBezier(t, SaveHumanoidRootPartPos, HitBox.Position, HitBox3.Position, HitBox2.Position)
end

–[[local BodyPosition = Instance.new(“BodyPosition”)
BodyPosition.position = BezierPosition
BodyPosition.maxForce = Vector3.new(50000, 50000, 50000)
BodyPosition.P = 25000
BodyPosition.Parent = Effect

local TweenData = TweenInfo.new(1,Enum.EasingStyle.Linear,Enum.EasingDirection.Out, 0, false, 0)
local Tween = TweenService:Create(BodyPosition,TweenData,{Position = BezierPosition})
Tween:Play()]]

Projectiles usually move in parabolas, not beziers

It can help to take a step back and answer these questions:

1. What inputs do you have (for example, do you have “start position” + “launch angle” or do you have “start position” + “target position” + “launch speed”, or some other combination)? What you choose affects the equations you need.

2. What output do you need? In other words, what is your ultimate goal? Are you just visualizing an arc in space? Are you planning to move a bullet along this path over time?

Also BTW, you can format code by surrounding it with backticks
```
like this
```
so it shows up

``````like this
``````
1 Like

I’m trying to create something similar to this.

Start position would be your character and end position would be a target.

1 Like

That visual helps a lot! I thought you meant like lobbing a rock into the air.

So what part are you having trouble with? Your `CubicBezier` function looks fine to me.

I’m trying to recreate the effect that I linked the functions may be fine but the loop needs a wait time. This is what I have and it’s very slow.

``````for t = 0, 1, 0.1 do
BezierPosition = QuadBezier(SaveHumanoidRootPartPos, HitBox.Position, HitBox2.Position, t)
local TweenData = TweenInfo.new(0.01,Enum.EasingStyle.Linear,Enum.EasingDirection.Out, 0, false, 0)
local Tween = TweenService:Create(BodyPosition,TweenData,{Position = BezierPosition})
Tween:Play()
wait()
end

(changed it to a quad bezier)``````

TweenService isn’t very helpful here, since it only gives you a straight interpolation. Not sure what that tweet used it for.

You just need to move some value from 0 to 1 over time and set the position based on that value every frame.

You could use `Stepped` to fire an update function every physics frame, and keep track of time:

``````local elapsedTime = 0
game:GetService("RunService").Stepped:Connect(function(time, deltaTime)
elapsedTime = elapsedTime + deltaTime
end)
``````

Then just divide `elapsedTime` by some multiplier (like, 2, if you want it to take 2 seconds to get to the goal) and use that as the `t` for your bezier.

Also, disconnect the `Stepped` event once you reach your goal:

``````local function Fire(part, p0, p1, p2, p3)
local elapsedTime = 0

local connection
connection = game:GetService("RunService").Stepped:Connect(function(time, deltaTime)
elapsedTime = elapsedTime + deltaTime

-- scale by speed factor
local t = elapsedTime / TRAVEL_TIME

local position
if t > 1 then -- reached end
position = p3
connection:Disconnect() -- fire no more
else
position = CubicBezier(t, p0, p1, p2, p3)
end

-- use position to place your part or whatever here
part.Position = position
end)
end
``````
1 Like

How would i make it travel at the same time tho?

You can coroutine it;coroutine | Roblox Creator Documentation
I use this whenever I don’t want my loops to stop my script

you’re the best, this worked perfectly fine