How to tween a NumberSequence

How do I tween a NumberSequence, can I?

Not directly, but you can always use an object that you can tween and map the value of that object to something you want to tween. In the example code below, I tweened a NumberValue and mapped the value of it to ColorSequence. You can use this code to gain a solid idea of how to do the same for a NumberSequence.

local TweenService = game:GetService('TweenService')
local NumberValue = Instance.new('NumberValue')

NumberValue:GetPropertyChangedSignal('Value'):Connect(function() -- Monitor NumberValue value change
	script.Parent.Color = ColorSequence.new({
		ColorSequenceKeypoint.new(0, Color3.new(1, 1, 1)),
		ColorSequenceKeypoint.new(NumberValue.Value, Color3.new()), -- Inserting the number value into the ColorSequenceKeypoint
		ColorSequenceKeypoint.new(1, Color3.new(1, 1, 1))
	});
end)

local NumberTween = TweenService:Create(NumberValue, TweenInfo.new(1), { Value = 1 }) -- Creating the tween for the NumberValue

NumberTween:Play()
NumberTween.Completed:Wait()
NumberValue:Destroy() -- Garbage collect the NumberValue, no longer being used
4 Likes

There is no built-in way to tween a number sequence. However, you can code it all yourself.

The general premise is to get the time value of every unique keypoint in both NumberSequences provided and interpolate the value at each time value by a provided alpha value. The diagram below explains this concept:

To create this, you need to create a function to evaluate the value at a certain time in a number sequence. To get the value of a NumberSequence given a time, you can do the following:

local function evalNumberSequence(sequence: NumberSequence, time: number)
	if time == 0 then
		return sequence.Keypoints[1].Value, sequence.Keypoints[1].Envelope
	elseif time == 1 then
		return sequence.Keypoints[#sequence.Keypoints].Value, sequence.Keypoints[#sequence.Keypoints].Envelope
	end

	--> looping through keypoints until the time value fits in between two adjacent keypoints
	for i = 1, #sequence.Keypoints - 1 do
		local current = sequence.Keypoints[i]
		local next = sequence.Keypoints[i + 1]
		if time >= current.Time and time < next.Time then
			local alpha = (time - current.Time) / (next.Time - current.Time)
			return
				current.Value + (next.Value - current.Value) * alpha,
				current.Envelope + (next.Envelope - current.Envelope) * alpha
		end
	end

	return 1, 1 --> value, envelope
end

This code is provided in the documentation for the NumberSequence datatype.

Then, you can get all the unique points between each number sequence, and interpolate these anchor point values by a provided alpha value. You can then use these acquired points

function(a: NumberSequence, b: NumberSequence, alpha: number)

	-->> retrieving unique points
	local pointTimes = {}
	for _, Keypoint in a.Keypoints do
		table.insert(pointTimes, Keypoint.Time)
	end
	for _, Keypoint in b.Keypoints do
		if not table.find(pointTimes, Keypoint.Time) then
			table.insert(pointTimes, Keypoint.Time)
		end
	end

	table.sort(pointTimes) --> make sure the points are in order

	-->> creating a new number sequence from interpolating all the values
	local keypoints = {}
	for _, pointTime in pointTimes do
		local valA, envA = evalNumberSequence(a, pointTime)
		local valB, envB = evalNumberSequence(b, pointTime)
		table.insert(
			keypoints,
			NumberSequenceKeypoint.new(
				pointTime,
				valA + (valB - valA) * alpha,
				envA + (envB - envA) * alpha
			)
		)
	end

	return NumberSequence.new(keypoints)
end

If you would like to use easing styles, you need to write the functions yourself. Here is a great resource that has code you can use to simulate the easing styles (note you have to convert this code to lua):

2 Likes