Help with bezier curve?

Hey, and thanks for reading in advance.

I’m making a little tower defense, and one of my units is called the Noobikaze - a small rocket-rider that crashes into the enemies headfirst while riding an explosive.

To run the visuals for this, I attempted to use a bezier curve to create a travel arc for the ‘fake’ display model, but I ended up failing pretty horribly - it’s been a long time since algebra, so I’m not sure what I’m doing wrong here…

The display ends up flying in an upward curve. I tried reducing the goal time of the second lerp by half, but that didn’t do the trick.

Code:

effects.Kamikaze = function(list)
	if list.figure then
		local start = list.start or Vector3.new()
		local target = list.target or Vector3.new()
		local tt = list.travel or 1

		local fake = list.figure:Clone()
		local rocket = fake:WaitForChild("Rocket")
		local base = fake:GetPrimaryPartCFrame()

		local mid = start + (target - start).Unit * (target - start).Magnitude		

		local goal = CFrame.new(target, target + (target - start).Unit)
		local upper = CFrame.new(mid + Vector3.new(0, 20, 0), target + (target - start).Unit)
		
		local now = tick()
		
		fake:SetPrimaryPartCFrame(CFrame.new(start, start + (target - start).Unit))
		rocket.Anchored = true; rocket.CanCollide = false
		fake.Parent = workspace.CurrentCamera
		
		spawn(function()
			while (tick() - now) < tt do
				local lerp1 = base:lerp(goal, (tick() - now)/tt)
				local lerp2 = goal:lerp(upper, (tick() - now)/tt)
				fake:SetPrimaryPartCFrame(lerp1:lerp(lerp2, (tick() - now)/tt))
				RUN.RenderStepped:wait()
			end

			effects.Sound({id = "rbxasset://sounds/collide.wav", v = .3, pos = rocket.Position})

			local boom = Instance.new("Explosion")
			boom.Position = rocket.Position
			boom.DestroyJointRadiusPercent = 0
			boom.BlastPressure = 0

			boom.ExplosionType = Enum.ExplosionType.NoCraters
			boom.Parent = workspace.CurrentCamera
			fake:Destroy()
		end)
	end
end

I looked at the API on the wiki and I’m fairly sure my math is correct here, but nonetheless the result I have is faulty, so any help or advice is appreciated!

1 Like

Firstly, the way you calculate mid seems to give a vector equal to target. I believe mid should be the average of the other two vectors, so try calculating it this way:

local mid = (start+target)*.5

Secondly, I believe you are using wrong CFrames in your while loop. You could also store (tick()-now)/tt into a variable

local t = (tick()-now)/tt
while t < 1 do
	local lerp1 = base:lerp(upper, t)
	local lerp2 = upper:lerp(goal, t)
	fake:SetPrimaryPartCFrame(lerp1:lerp(lerp2, t)
	RUN.RenderStepped:wait()
	t = (tick()-now)/tt
end

I recommend checking out this article about Bezier Curves: Bézier Curves | Documentation - Roblox Creator Hub.

Yup, that did the trick! Rotation’s a bit off, but I think that’s because the mesh is backwards and I forgot to account for it. Thanks!