local function leap(character : Model, distance : number, height : number)
local root = character:FindFirstChild("HumanoidRootPart")
local distance = distance
local height = height
local pointA = root.CFrame
local pointC = pointA*CFrame.new(0,0,distance)
local pointB = pointA:lerp(pointC,0) * CFrame.new(0,height,0)
for i = 0, 1, .1 do
root.CFrame = pointA.Rotation + Util:QuadraticBezier(i,pointA.Position,pointB.Position,pointC.Position)
task.wait(0.01)
end
end
Unfortunately, it seems like having a set speed is a bit more complicated than just changing the wait time. From what I’ve seen in the threads I linked you have to do some kind of calculation for the time or speed.
The end of this briefly talks about making the spacing more even and supplies some approximation code. (though it is based on their implementation of course)
local function leap(character : Model, distance : number, height : number)
local root = character:FindFirstChild("HumanoidRootPart")
local distance = distance
local height = height
local pointA = root.CFrame
local pointC = pointA*CFrame.new(0,0,distance)
local pointB = pointA:lerp(pointC,0) * CFrame.new(0,height,0)
local seconds = 1 --the amount of seconds you want it to take to complete the jump
local current = 0
while current <= seconds do
local i = current/seconds
root.CFrame = pointA.Rotation + Util:QuadraticBezier(i,pointA.Position,pointB.Position,pointC.Position)
current = current + wait()
end
end
When you say “speed” I’m assuming you mean a target velocity (studs per second). Calculating the real length of a bezier curve is quite expensive so you can try estimating the length by cutting the bezier into segments and adding the magnitude (distance) between each of the points:
I came up with this for my module:
function module:EstimateQuadraticBezierLength(p0: CFrame, p1: CFrame, p2: CFrame, amountOfSegments: number?)
local amountOfSegments: number = amountOfSegments or 10
local segments: {Vector3} = {}
for i = 1, amountOfSegments do
table.insert(segments, module:QuadraticBezier(p0.Position, p1.Position, p2.Position, i / amountOfSegments))
end
local length = 0
for i = 1, amountOfSegments do
local this, next = segments[i], segments[i + 1]
if not next then
continue
end
length += (this - next).Magnitude
end
return length
end
More segments means more accuracy but in turn it’s also more expensive.
Anyway, your duration will now be the estimated bezier length divided by your goal velocity, so
-- assume p0, p1 and p2 are all Vector3's
local duration = util:EstimateQuadraticBezierLength(p0, p1, p2, 10) / goalVelocity
-- then finally for the loop we can just make a variable that continually increases until it's equal or greater than duration, but we also divide this by our duration to get a number between 0 and 1 for the position along the curve:
local timePassed = 0
while timePassed < duration do
util:QuadraticBezier(p0, p1, p2, timePassed / duration)
timePassed += task.wait()
end
Hello, my bad for the necroposting, but for future users reading this: does this also work on higher degree Bézier functions?
If so, then what do we need to change?
The current problem that I’m facing is trying to make the moving part rotate along its trajectory.
In the usual Bézier curve approach (where the total time passed between the movement is constant), this is easy to accomplish with a for loop (I made a post on this last weekend: How do I make a rocket point towards its trajectory?).
Basically, I’m making using the CFrame.lookAt() function to make it look at its following position.
Since this is using a while loop instead of a for loop, how would doing this be possible?
If I’m understanding your question correctly, for your next point for the second argument of lookAt, you’d just get a point that’s slightly further along the curve, say 0.01 + t, where t is the current time
Hey, I’m aware this may not be what you are looking for but perhaps a combination of AlignPosition and this module would help? This module is so much help for me and is truly amazing and removes all headache from bezier curve by defining it all into one simple function from loading the module …
Hope this helps
Code Example:
local Bezier = require(--[[reference bezier module script]])
local function leap(character : Model, distance : number, height : number)
local root = character:FindFirstChild("HumanoidRootPart")
local distance = distance
local height = height
local pointA = root.CFrame
local pointC = pointA*CFrame.new(0,0,distance)
local pointB = pointA:lerp(pointC,0) * CFrame.new(0,height,0)
local tweenTime = 1 --how long the bezier curve should take
Bezier.new(pointA.Position, pointB.Position, pointC.Position)
local b = Bezier:CreateCFrameTween(root, {"CFrame"}, TweenInfo.new(tweenTime))
b:Play()
task.delay(b.TweenInfo.Time, b.Destroy, b)
end