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

Help with Scripting Animations?

Asked by 8 years ago

So i am looking to create a basic function that i can use to animate parts through a script. I decided to go down the path of CFraming since it is the most customizable compared to other forms like motors. so i wrote this general purpose function but my math skills aren't at a very high level so can someone tell me if im on the right track with this and how i can improve it

function TweenJoint(joint, newCFrame, Time) 
    -- where joint is the part being moved,
    -- newCFrame is the end pose  
    -- Time is the length of the animation in seconds

    local length = Time -- in seconds
    local Frames = 25
    local TotalSteps = Frames * length
    local CFStep = (joint.CFrame - newCFrame) / TotalSteps

    for i = 0, TotalSteps do
        joint.CFrame = joint.CFrame + CFStep
        wait(1/Frames)
    end
end

1 answer

Log in to vote
2
Answered by
EgoMoose 802 Moderation Voter
8 years ago

There are actually a few ways to tween CFrames, but to keep things simple let's just keep it to what you suggested, linear interpolation (LERP).

The basic math behind lerping is:

-- a is start, b is end, c is the percentage between the two
function lerp(a, b, c)
    return a + ((b - a) * c);
end;

With this basic equation we can get a value between two points linearly. Now some clarification, linear doesn't mean the way we change c (as I'll explain in a bit), but rather that we essentially get from point a to be in a straight line. From a number standpoint this doesn't make much sense, but once we get into 3D this can become convoluted. Regardless, that's a topic for another time (google SLERP if you dare :P)

Right, so now that we understand the basis of lerping let's make our own CFrame lerp function:

function lerpCf(a, b, c)
    local newCf = {};
    local a, b = {a:components()}, {b:components()};
    for i = 1, 12 do -- 12 components in a CFrame
        newCf[i] = a[i] + ((b[i] - a[i]) * c); -- lerp equation
    end;
    return CFrame.new(unpack(newCf));
end;

Now luckily for us, Roblox has a built in lerp method (that I think might be more accurate(?)) so we don't have to have this function in our code. That being said, it's still useful to understand it.

So onto the tween. We have 3 pieces of information. The start CFrame, the end CFrame, and the time. So taking a look at that information and what we need for a lerp what are we missing? -- The c-value our percentage!

The question becomes how do we translate our time into that c-percentage? The answer is to use tick:

function tweenCf(child, property, goal, t)
    local start = child[property];
    local stime, ctime = tick(), 0;
    while ctime < t do -- keep updating as long as time passed is < the tween length
        ctime = (tick() - stime); -- how much time has passed
        child[property] = start:lerp(goal, ctime/t); -- percentage of current time passed
        wait(0); -- use renderstepped if you can
    end;
    child[property] = goal; -- set to the goal value incase of float math errors, etc
end;

Now as mentioned above, we can also change how we handle the c-value by playing with what are called easing functions. They essentially change how the c-value move. Eg. It might be really fast at the start and slow down at the end, but it'll still add up to t seconds passed.

Here's an example:

function tweenCf(child, property, goal, t, ease)
    local start = child[property];
    local stime, ctime = tick(), 0;
    while ctime < t do
        ctime = (tick() - stime);
        child[property] = start:lerp(goal, ease(ctime, 0, 1, t)); -- easing function
        wait(0);
    end;
    child[property] = goal;
end;

function inOutQuad(t, b, c, d)
    t = t / d * 2;
    if t < 1 then
        return c / 2 * math.pow(t, 2) + b;
    else
        return -c / 2 * ((t - 1) * (t - 3) - 1) + b;
    end;
end;

local part = game.Workspace.Part;
tweenCf(part, "CFrame", CFrame.new(15, 15, 15) * CFrame.Angles(math.pi/4, math.pi/4, math.pi/4), 2, inOutQuad);

Here's a bit list of easing functions pre-written! https://github.com/EmmanuelOga/easing/blob/master/lib/easing.lua

0
Thank you this was extremely helpful ProfessorSev 220 — 8y
Ad

Answer this question