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

Help with Scripting Animations?

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

✓ Accepted answer

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

1 comment

0

Thank you this was extremely helpful

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