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 :slight_smile:

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.
They had said it was made using beziers and tweens.

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

https://twitter.com/i/status/1260695863694888961

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
3 Likes

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