Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

How to use CFrame:Lerp() to move object?

2 answers

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!

1 comment

0

Whew! 172 lines?! As someone who isnt learning this much in math yet, this math is CONFUSING! Thanks for the help though! I'll look through and try to figure it out.

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!

This discussion is preserved as it was. New answers, comments, and votes are closed.