Tweening an Integer

After searching for hours on Google to try and find a simple tweening function, my search ended in failure. If anyone could help by providing some assistance with a tweening function for either a single number or a Vector3, that’d be much appreciated.

Why?
I’m working on a camera manipulation system that I would like to add Character leaning to. To accomplish this, the best way is to tween a Vector3 or a number so that the main camera equation doesn’t experience movement bugs.

Note: TweenService requires an object and I would rather not go through the trouble of creating a hacky way to support it.

2 Likes

To tween a simple Vector3 or integer, you can always tween things like a NumberValue, Vector3Value, or CFrameValue. When tweening them, you’ll need a very fast loop to edit the Camera properties relative to these values in their tween. Just keep in mind you should always stop the loop after it’s done.

5 Likes

The problem with that is I would rather not have an external object that my scripts rely on. Hence why I’m asking for an internal function. However, I will probably have to use this option. Thank you for the help.

1 Like

You could try creating table that gets appended to with tween information every time you create a new tween. Then have a function that calculates all of the tweens based off of that information at renderstep. But it would be much easier to use tweenservice on values.


Lerp function:

function Lerp(a, b, c)
    return a + ((b - a) * c)
end

This could be useful.

c is the fraction of the interpolation. E.g: if you are interpolating a = 2 to b = 4, when c = 0.5, the function will return 3.

c is only between 0 and 1

5 Likes

I found this kind of function while googling it as a Quadratic In/Out tween. However, I was unable to figure out how to implement that into a functional tween system.

EDIT: I did experiment with it in Roblox.

TweenService has a function specifically for getting tween alphas, TweenService:GetValue. You can use that to tween integers like so:

int1 = 5
int2 = 10

local i = 0
while i < 1 do
	i = math.clamp(i + --[[ increment ]],0,1)
	local a = TweenService:GetValue(i,--[[ EasingStyle ]],--[[ EasingDirection ]])

	--rounds to the nearest integer
	local tweenInt = math.round(int1*(1 - a) + int2*a)
	
	--[[ normal number tween looks like this
	local tweenNumber = num1*(1 - a) + num2*a
	--]]
	print(tweenInt)
end

And you can do the same with Vector3s:

local v1 = Vector3.new(0,0,0)
local v2 = Vector3.new(0,10,0)

local i = 0
while i < 1 do
	i = math.clamp(i + --[[ increment ]],0,1)
	local a = TweenService:GetValue(i,--[[ EasingStyle ]],--[[ EasingDirection ]])
	local tweenVector = v1*(1 - a) + v2*a
	print(tweenVector)
end
5 Likes

You can tween a number linearly by using a + (b - a)*c where a and b are your start and finish and c is your alpha (some decimal at or between 0 and 1).

You can also use CFrame:lerp(cf,c) and Vector3:Lerp(v3,c) to lerp their respective userdatas.

Finally, you can convert c to run on another tween style, like so:

local c = .75
c = .5 - .5 * math.cos(math.pi*c) -- throw our first val into the conversion formula
print(c)
>> .853553390593

That example was a in-out sine curve. Afterwards you would throw that final c variable into your lerp function, and the outcome will be your current value.

But in all honesty, you should use what goldenstein says and go with TweenService. It’ll save you a ton of time, only if you use the actual TweenService:Create() function though.

2 Likes

It works almost perfectly. However, it’s buggy. https://gyazo.com/5a250ffbdc827afcfd80f0db7e63faa1

EDIT: Here’s the translated equation:

local i = 0;
    while i < 1 do
        i = math.clamp(i + 1/60,0,1)
        local a = game:GetService("TweenService"):GetValue(i,Enum.EasingStyle.Quad,Enum.EasingDirection.InOut);
        CameraPos.Value = CameraPos.Value*(1-a)+CAMERALEANLEFT*a;
    wait(1/60);
end

I made an uncopylocked bezier curve simulator that uses this very lerp functions. You can view it here.


Anyways you simply run a for loop, and every iteration, you adjust the value of something. For example:

local Increment = 1/10 --How detailed your lerp will be. 1/10 = 0.1.
local StartVector = Vector3.new(5, 5, 5)
local EndVector = Vector3.new(15, 20, 25)

local Part = workspace.Part --Assuming there is already a part there

function Lerp(a, b, c)
    return a + ((b - a) * c)
end


for Fraction = 0, 1, Increment do --1/0.1 = 10 iterations
    Part.Position = Lerp(StartVector, EndVector, Fraction)
    wait()
end

Fraction and Increment will always be between or equal to 0 and 1. When Increment at 0, the part will be at the StartVector. When Increment is at 1, the part will be the the EndVector.

4 Likes

Try printing a or i each increment and see how it’s changing, and you can also try using Vector3:Lerp, which might yield less glitchy results?

Use a bool variable that is true when the Lerp is playing. Only allow another Lerp to occur when the bool is false. I used this technique when experiencing overriding tweens, which solved the problem.


Or just use the :Lerp() function or TweenService whilst using the bool / debounce technique.

1 Like

After attempting each of these responses, I’ve found that using the Vector3 Object Value is much easier than attempting any internal equations. (As well as that, these equations are “laggy” and I can’t change the speed without compensating for detail)

Thank you everyone.

Have you tried this, yet? This solved my issue before.

Yes, I already had that implemented. It didn’t seem to do anything.

To make it not so buggy you would need to bind it to renderstep and redo the math for what determines “i”.

1 Like

Um, I know it’s been 2 years, so I’m probably too late. But for all the people who found this later. pretty much all of the advice here, (at least of what I’ve seen) is kinda either spaghetti-ish or outdated

here’s how how you can tween a camera with a few lines of code

local tweenInfo = TweenInfo.new(
	1,
	Enum.EasingStyle.Linear,
	Enum.EasingDirection.Out,
	0,
	false,
	0	
)

workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable
local tween2 = tweenService:Create(workspace.CurrentCamera, tweenInfo, {CFrame = cameraPosition})
tween2:Play()
1 Like

without creating a instance you can probably use attributes

Not sure why this thread was bumped but you can get a tweened value with TweenService:GetValue, similar to linear interpolation where you pass the initial, goal and alpha and get an eased result.