local function QuadraticBezier(t,p0,p1,p2)
return (1-t)^2*p0+2*(1-t)*t*p1+t^2*p2;
end;
local Part0 = workspace.Start;--<Start point
local Part1 = workspace.Bend;--<'Curve' Point
local Part2 = workspace.End;--<End Point
for t = 0,1,0.01 do
local TargetPosition = QuadraticBezier(t , Part0.Position, Part1.Position, Part2.Position);
local inter_PART = Instance.new("Part", workspace);--<Part To Move
inter_PART.Position = TargetPosition;
inter_PART.Anchored = true
end;
I used this code to duplicate these parts in the form of a curve.
The issue:
If you look at this picture it shows them positioned in the curve, but their orientation is not facing the next part. How can I fix this?
I had a similar issue whilst creating a pathfinding script and solved it using this:
-- where:
-- p2 = the part created
-- last2 = the last part that was created (if it is nil then make the part transparent)
-- b = bezier curve module i did not make
-- :GetPoint(i) = gets a point on a bezier in a percentage
p2.Size = Vector3.new(2,2,(last2.Position - b:GetPoint(i)).Magnitude*1.5)
p2.CFrame = CFrame.new(b:GetPoint(i), last2.Position)
local function QuadraticBezier(t,p0,p1,p2)
return (1-t)^2*p0+2*(1-t)*t*p1+t^2*p2;
end;
local Part0 = workspace.Start;--<Start point
local Part1 = workspace.Bend;--<'Curve' Point
local Part2 = workspace.End;--<End Point
for t = 0,1,0.01 do
local TargetPosition = QuadraticBezier(t , Part0.Position, Part1.Position, Part2.Position);
local inter_PART = Instance.new("Part", workspace);--<Part To Move
inter_PART.Name = t
local PreviousTargetPosition = QuadraticBezier(t - 0.01 , Part0.Position, Part1.Position, Part2.Position)
inter_PART.CFrame = CFrame.lookAt(TargetPosition, PreviousTargetPosition)
inter_PART.Anchored = true
end;
THANK YOU!!
IT nearly worked, but Im not sure why these gaps occur, any ideas?
for t = 0,1,0.01 do
local TargetPosition = QuadraticBezier(t , Part0.Position, Part1.Position, Part2.Position);
local inter_PART = Instance.new("Part", workspace);--<Part To Move
inter_PART.Position = TargetPosition;
inter_PART.CFrame = CFrame.new(inter_PART.Position,workspace.End.Position);
inter_PART.Anchored = true
end;
Letting the parts face the next part is inaccurate, instead you should calculate the derivative, which is the part’s correct LookVector.
Calculating the position:
--from github.com/bstummer/bezier
local function getPos(t: number, points: {Vector3}): Vector3
local copy = {unpack(points)}
local n = #copy
for j = 1, n - 1 do
for k = 1, n - j do
copy[k] = copy[k] * (1 - t) + copy[k + 1] * t
end
end
return copy[1]
end
Calculating the derivative:
--from github.com/bstummer/bezier
local function fac(n: number): number
local f = 1
for i = 1, n do
f *= i
end
return f
end
local function getDerivative(t: number, points: {Vector3}): Vector3
local result = Vector3.zero
local n = #points - 2
for i = 0, n do
result += (fac(n)/(fac(i)*fac(n-i))) * t^i * (1-t)^(n-i)
* (points[i+2] - points[i+1])
end
return result * (n+1)
end
Visualizing the path:
for t = 0, 1, 0.1 do
local pos = getPos(t, points)
local der = getDerivative(t, points)
local part = Instance.new("Part")
part.Anchored = true
part.CFrame = CFrame.lookAt(pos, der + pos)
part.Size = Vector3.one
part.TopSurface = Enum.SurfaceType.Smooth
part.BottomSurface = Enum.SurfaceType.Smooth
part.Parent = workspace
end
You can also use CFrame points instead of Vector3. This automatically calculates the orientation.
--from github.com/bstummer/CutsceneService
local function getCF(t: number, points: {CFrame}): CFrame
local copy = {unpack(points)}
local n = #copy
for j = 1, n - 1 do
for k = 1, n - j do
copy[k] = copy[k]:Lerp(copy[k + 1], t)
end
end
return copy[1]
end