Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

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

Asked by 3 years ago

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?

2 answers

Log in to vote
0
Answered by
TGazza 1336 Moderation Voter
3 years ago

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!

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. Turtleraptor372 5 — 3y
Ad
Log in to vote
0
Answered by 3 years ago

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!

Answer this question