So i've been wanting to use bezier curves, and i know you need to use :lerp() to move something along the curve. The problems is, I have no clue how to move using :Lerp(). Would you just move the position along the line made using :Lerp(), or is there another way of doing this?
I did do a script that creates a Bézier curve. I made this script a few years ago.I just went through it and updated it and it Should work. Your free to use/study the code.
Code:
local modelGrp = workspace:FindFirstChild("Stem Group") if(modelGrp == nil) then modelGrp = Instance.new("Model",workspace) modelGrp.Name = "Stem Group" end function doStrand(name,firePos,TargPos,Properties,parent) local Sides = {"Front","Back","Top","Bottom","Left","Right"} local P = parent:FindFirstChild(name) if(P == nil) then P = Instance.new("Part",parent) P.formFactor = "Custom" P.Transparency = 0 P.Reflectance = 0 P.Name = name P.Locked = true P.CanCollide = false P.Shape = "Cylinder" P.Anchored = true for i=1,#Sides do P[Sides[i].."Surface"] = "SmoothNoOutlines" end for k,v in pairs(Properties) do if(k ~= "Size") then P[k] = v end end end P.Size = Vector3.new((firePos - TargPos).magnitude,Properties.Size.x,Properties.Size.y) P.CFrame = CFrame.new((firePos + TargPos)/2,firePos)*CFrame.Angles(0,math.rad(90),0) return P end function CalculateBezierPoint(t, p0, p1, p2, p3) local u = (1 - t); local uu = u*u; local uuu = uu * u; local tt = t*t; local ttt = tt * t; local p = uuu * p0; -- first term p = p + 5 * uu * t * p1; --second term p = p + 5 * u * tt * p2; --third term p = p + ttt * p3 --fourth term return p; end function ChangeV3(Pos,GtoPos,mod) local x = Pos.x local y = Pos.y local z = Pos.z if(x > GtoPos.x) then if(x-mod < GtoPos.x) then x = GtoPos.x else x = x -mod end elseif(x < GtoPos.x) then if(x+mod > GtoPos.x) then x = GtoPos.x else x = x +mod end else x = x end if(y > GtoPos.y) then if(y-mod < GtoPos.y) then y = GtoPos.y else y = y -mod end elseif(y < GtoPos.y) then if(y+mod > GtoPos.y) then y = GtoPos.y else y = y +mod end else y = y end if(z > GtoPos.z) then if(z-mod < GtoPos.z) then z = GtoPos.z else z = z -mod end elseif(z < GtoPos.z) then if(z+mod > GtoPos.z) then z = GtoPos.z else z = z +mod end else z = z end return Vector3.new(x,y,z) end local Points = { Stem = { Pos = {Vector3.new(0,0,0), Vector3.new(0,5,0), Vector3.new(0,10,0), Vector3.new(0,15,0)}, Goals = {Vector3.new(0,0,0),Vector3.new(0,5,0), Vector3.new(0,10,0), Vector3.new(0,15,0)} } } local createWeight = function(point,name) local CP = workspace:FindFirstChild(name) local Faces = {"TopSurface","BottomSurface","LeftSurface","RightSurface","FrontSurface","BackSurface"} if(CP == nil) then CP = Instance.new("Part",workspace) CP.Anchored = true CP.Name = name CP.FormFactor = "Custom" CP.Shape = "Ball" CP.Transparency = 0.4 CP.Size = Vector3.new(2,2,2) for f=1,#Faces do CP[Faces[f]] = "SmoothNoOutlines" end end CP.CFrame = point return CP end local step = 0.1 local StemBaseSize = 2 local SEGMENT_COUNT = 50 local CPoints = {} for i=1,#Points.Stem.Goals do local name = (i >1 and i < 4) and "ControlPoint ["..(i-1).."]" or (i == 1) and "Start Point" or "End Point" CBrick = createWeight(CFrame.new(Points.Stem.Goals[i]),name) CPoints[i] = CBrick end local myStyle = { BrickColor = BrickColor.new("Bright green"), Material = Enum.Material.SmoothPlastic, Size = Vector2.new(0.2,0.2), Shape = "Cylinder" } local SIndex = 0 function scale(valueIn, baseMin, baseMax, limitMin, limitMax) return ((limitMax - limitMin) * (valueIn - baseMin) / (baseMax - baseMin)) + limitMin; end function drawWeightLine(Goal,id) local myStyle = { BrickColor = BrickColor.Black(), Material = Enum.Material.SmoothPlastic, Size = Vector2.new(0.2,0.2), Transparency = 0.7 } local Segs = modelGrp:GetChildren() local Dist = math.huge local ClosestPoint = nil for i=1,#Segs do local dist = (Goal - Segs[i].Position).magnitude if(dist < Dist) then ClosestPoint = Segs[i] Dist = dist end end if(ClosestPoint ~= nil) then doStrand("Weight Line ["..id.."]",ClosestPoint.Position,Goal,myStyle,workspace) end end while true do local StemPos = Points.Stem.Pos local StemGoals = Points.Stem.Goals for i=1,#StemPos do StemGoals[i] = CPoints[i].Position step = (StemPos[i] - StemGoals[i]).magnitude/4 StemPos[i] = ChangeV3(StemPos[i],StemGoals[i],step) end --print(StemGoals[2]) for s = 0, SEGMENT_COUNT do local name = "Part "..s local t = s / SEGMENT_COUNT; local tu = (s >0) and (s-1) / SEGMENT_COUNT or 0 pixel = CalculateBezierPoint(t, StemPos[1], StemPos[2], StemPos[3], StemPos[4]); Prev = CalculateBezierPoint(tu, StemPos[1], StemPos[2], StemPos[3], StemPos[4]); Seg = doStrand(name,pixel,Prev,myStyle,modelGrp) end for i=1,#StemGoals do drawWeightLine(StemGoals[i],i) end SIndex = (SIndex < SEGMENT_COUNT) and SIndex+1 or 0 wait() end
The script runs creates a vertical line with 4 spheres acting as weights. Move the spheres and you'll see the Line move, kinda like the Photoshop Bézier curve tool.
If I had a chance to re-make the script it would be a lot neater as I was learning to code at the time I made this script so sorry for the mess lol.
I was thinking you could rather than create the vertical line you could record the positions as if they were a path.
Hope this helps!
Thanks for the help! That link helped me figure it out. I basically just change the position between two points using CFrame:Lerp() in a for loop. To do the curve, i just plugged the time and others parameters into the function through an equation and move the object there. I honestly dont understand how the equation works, but at least I know how to use curves now. Thanks for the help!