How do I utilise this module to create a projectile along a Bezier curve with a constant speed

So I have been working to create bezier curve projectiles and while I’ve had some luck, I’ve been facing an issue where the projectile will not run a fixed speed along the bezier curve, often slowing down and speeding up at different points across a curve, obviously for a projectile this motion is unrealistic (e.g a fireball or a basketball) and not the result I require.

I did some reading on this guide which was quite helpful but a little confusing.

It says I have to perform something called "Arc Length Parameterization on the bezier curve, but with the module they give I am unsure on how to implement the module, especially as they did not give an example.

For reference, this is the module they provided and I would like to know if anyone can help me out, preferably providing an example of this module in use to help my understanding of this module.

local bezier = {}

function length(n, func, ...)
	local sum, ranges, sums = 0, {}, {}
	for i = 0, n-1 do
		local p1, p2 = func(i/n, ...), func((i+1)/n, ...)
		local dist = (p2 - p1).magnitude
		ranges[sum] = {dist, p1, p2}
		table.insert(sums, sum)
		sum = sum + dist
	end
	return sum, ranges, sums
end

function bezier.new(func, n, ...)
	local self = setmetatable({}, {__index = bezier})
	local sum, ranges, sums = length(n, func, ...)
	self.func = func
	self.n = n
	self.points = {...}
	self.length = sum
	self.ranges = ranges
	self.sums = sums
	return self
end

function bezier:setPoints(...)
	-- only update the length when the control points are changed
	local sum, ranges, sums = length(self.n, self.func, ...)
	self.points = {...}
	self.length = sum
	self.ranges = ranges
	self.sums = sums
end

function bezier:calc(t)
	-- if you don't need t to be a percentage of distance
	return self.func(t, unpack(self.points))
end

function bezier:calcFixed(t)
	local T, near = t * self.length, 0
	for _, n in next, self.sums do
		if (T - n) < 0 then break end
		near = n
	end
	local set = self.ranges[near]
	local percent = (T - near)/set[1]
	return set[2], set[3], percent
end

return bezier

note: this was intended for a module script ^

Thank you for reading, I appreciate any response as I have been figuring this out for a while.

You cannot make a bezier curve have a specific speed over its whole length. Try a Hermite spline instead, which lets you specify the start and end speed.

that article pushing the use of oop is overkill and unnecessary

i had the exact same issue a few months ago and i made a bezier curve function:

--variable *a* is number within -> [0, 1]
local function Bezier(P0: CFrame | Vector3, P1: CFrame | Vector3, P2: CFrame | Vector3, a: number): CFrame | Vector3
	local L0 = P0:Lerp(P1,a)
	local L1 = P1:Lerp(P2,a)
	return L0:Lerp(L1,a)
end

i use this in conjunction with RunService.Heartbeat, constantly adding the elapsed time (total time + deltaTime) per frame to achieve uniform movement for my Bezier projectiles