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:
- Model: NumberSequenceMultiplier - Roblox (for people who just want to have it on them without opening the DevForum post)
--[[
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!