NumberSequenceMultiplier - Tweening number sequences in multipliers

Introduction:

I recently needed a function similar to this for my game and I wanted to make the size of a particle emitter to go up in a tween and couldn’t find a native way to do it so I created my own module. This is only helpful depending on your use-case.

Anyways, that’s pretty much all there is to it. I don’t actually know how to record a gif on this laptop so there’s no showcase. If anyone else can upload one that’d be nice.

Usage example:

local sequenceMultiplier = ... --> module path here somewhere
-- Tweens the particle emitter's size by 10x in 3 seconds
local tween = sequenceMultiplier.new(particleEmitter,3,10,"Size")
-- methods:
tween:Play() -- Play the tween
tween:Cancel() -- Cancel the tween
tween:Pause() -- Pause the tween
tween:Destroy() -- Destroy and clean up signals
tween:GetOriginalPoints() -- Returns the particle emitter's original size before it was tweened

Code:

--[[

	Author: @Jumpathy
	Description: Tweens the size of a 'NumberSequence' on a part in coefficients.
	Reference / partial-credit: https://developer.roblox.com/en-us/api-reference/datatype/NumberSequence

]]

local tweenService = game:GetService("TweenService");
local multiplier = 1000; --> Tweening smoothness basically, the lower it is the less accurate it'll be.
local check = {};

local getPointFromNumberSequence = function(sequence,timeStamp)
	if(timeStamp == 1) then 
		return sequence.Keypoints[#sequence.Keypoints].Value;
	elseif(timeStamp == 0) then
		return sequence.Keypoints[1].Value;
	end
	for i = 1,#sequence.Keypoints - 1 do
		local this = sequence.Keypoints[i];
		local nextKeypoint = sequence.Keypoints[i + 1];
		if(timeStamp >= this.Time and timeStamp < nextKeypoint.Time) then
			local alpha = (timeStamp - this.Time) / (nextKeypoint.Time - this.Time);
			return(nextKeypoint.Value - this.Value) * alpha + this.Value;
		end
	end
end

local getPoints = function(numberSequence)
	local points = {};
	local pointAmount = 20; --> engine limit
	for i = 1,(pointAmount - 1) do
		local inTime = 1/i;
		table.insert(check,1,inTime);
	end
	table.insert(check,1,0);
	for _,pointTime in pairs(check) do
		local a,b = pointTime,getPointFromNumberSequence(numberSequence,pointTime);
		table.insert(points,{a,b})
	end
	check = {};
	return points;
end

local module = {};

function module.new(object:Instance,length:number,goal:number,property:string)
	local points = getPoints(object[property]);
	local numSequence = {};
	local tbl = {};
	local numValue = Instance.new("NumberValue");
	numValue.Value = 0;

	local toTween = {["Value"] = goal * multiplier};
	local tweenInstance = tweenService:Create(numValue,TweenInfo.new(length,Enum.EasingStyle.Linear),toTween);
	local finishedSignal;

	local changedSignal = numValue.Changed:Connect(function()
		tbl = {};
		for key,point in pairs(points) do
			numSequence[key] = numSequence[key] or {};
			numSequence[key][1] = point[1];
			numSequence[key][2] = point[2] * (numValue.Value / multiplier);
		end
		for key,v in pairs(numSequence) do
			tbl[key] = NumberSequenceKeypoint.new(unpack(v));
		end
		object[property] = NumberSequence.new(tbl);
	end)

	local cleanUp = function()
		if(finishedSignal) then
			finishedSignal:Disconnect();
		end
		changedSignal:Disconnect();
		tbl = nil;
		numValue:Destroy();
	end

	finishedSignal = tweenInstance.Completed:Connect(cleanUp);
	
	-- Return:
	
	local methods = {};

	function methods:Play()
		tweenInstance:Play();
	end

	function methods:Cancel()
		tweenInstance:Cancel();
	end

	function methods:Pause()
		tweenInstance:Pause();
	end

	function methods:Destroy()
		cleanUp();
	end

	function methods:GetOriginalPoints()
		local new = {};
		for key,point in pairs(points) do
			new[key] = NumberSequenceKeypoint.new(unpack(point));
		end
		return NumberSequence.new(new);
	end

	return methods;
end

return module;

Enjoy, anyone who might find this helpful!

13 Likes

Cool resource, thanks! I can’t obtain it though, I think you forgot to make it public.

2 Likes

This is super cool! If you’re interested in tweening NumberSequences, I’d also recommend BoatTween:

1 Like

Fixed, my bad lol

I didn’t know that was thing, very interesting. Do you have a sample code that would work for it? I’m too lazy to read the docs for it.

1 Like

It works pretty similarly to the tween service, so it doesn’t have a built in way to multiply NumberSequences. It can tween NumberSequences to new NumberSequences though.

Here is a code example from the article:

local BoatTween = require(script.BoatTween)

local Tween = BoatTween:Create(workspace:WaitForChild("Part"),{
	Time = 4;
	EasingStyle = "EntranceExpressive";
	EasingDirection = "In";
	
	Reverses = true;
	DelayTime = 1;
	RepeatCount = 3;
	
	StepType = "Heartbeat";
	
	Goal = {
		Color = Color3.new(0.5,0.2,0.9);
		Position = Vector3.new(4,10,7);
		Transparency = 0.5;
	};
})
Tween:Play()

If you were doing a particle emitter, you could just change the part that gets the part to something that gets a ParticleEmitter then change the goal to something like:

{Size = NumberSequence.new()}
2 Likes