Hi! I’m creating a storm system that has an “animation” effect by constantly updating the CFrame of some cloud meshes. And although I’m satisfied with the appearance, the performance, on the other hand, is horrid due to the amount of parts being created (which are also destroyed after a certain amount of time). Here’s my code (or at least a part of my code involving the “animate” local functions which are connected in parallel with RunService.Heartbeat):
local function cloudBaseAnimateDo(): nil -- GOOD
for _, cloudBase in pairs(baseCloudFolder:GetChildren()) do
local angleDistanceVal = cloudBase.angleDistanceVal;
local rotationVal = cloudBase.rotationVal;
if(angleDistanceVal.Value <= 0) then
task.synchronize();
cloudBase:Destroy(); -- For now just have it destroy
else
task.synchronize();
cloudBase.CFrame = centerPart.CFrame
* CFrame.fromEulerAnglesXYZ(0, rotationVal.Value, 0)
* CFrame.new(0, 1000, angleDistanceVal.Value * someWeatherVal.Value);
angleDistanceVal.Value -= 0.5; -- 0.5 for LP
rotationVal.Value += 0.0007; -- 0.0007 for LP
end
task.desynchronize();
end
end
-- "Animates" the cumulonimbus clouds by giving them a rotation effect
local function cumulonimbusAnimateDo(): nil -- GOOD
for _, cumulonimbusSubFolder in pairs(cumulonimbusFolder:GetChildren()) do
local positionalVal = cumulonimbusSubFolder.positionalVal;
local offsetVal = cumulonimbusSubFolder.offsetVal;
-- VVVV Will need to change this later (just calculate the distance for that)
if(positionalVal.Value.Y >= 25176) then
task.synchronize();
cumulonimbusSubFolder:Destroy() -- For now just have it destroy
task.desynchronize();
else
task.synchronize();
offsetVal.Value += Vector3.new(0, 1, -0.7);
positionalVal.Value = ((centerPart.CFrame + Vector3.new(0, 300, 0))
* CFrame.new(offsetVal.Value)).Position;
task.desynchronize();
for _, cumulonimbus in pairs(cumulonimbusSubFolder:GetChildren()) do
if(cumulonimbus:IsA("Part")) then
local rotationVal = cumulonimbus.rotationVal;
local posVal = cumulonimbus.positionalVal;
task.synchronize();
rotationVal.Value += 0.0006;
cumulonimbus.CFrame = CFrame.new(positionalVal.Value)
* CFrame.fromEulerAnglesXYZ(0, rotationVal.Value, 0)
* CFrame.new(posVal.Value.X, 0, posVal.Value.Z);
task.desynchronize();
end
end
end
end
end
-- "Animates" the upper cumulonimbus clouds
local function upperCumulonimbusAnimateDo(): nil -- GOOD
for _, cumulonimbus in pairs(upperCumulonimbusFolder:GetChildren()) do
local positionalVal = cumulonimbus.positionalVal;
if(positionalVal.Value.Z <= -42000) then
task.synchronize();
cumulonimbus:Destroy();
task.desynchronize();
else
if((positionalVal.Value.Y >= 23000) and not cumulonimbus.isAnvil.Value) then
task.synchronize();
cumulonimbus.isAnvil.Value = true;
tweenService:Create(cumulonimbus.cloudMesh,
TweenInfo.new(65, Enum.EasingStyle.Linear),
{Scale=Vector3.new(13000, 2000, 13000)}):Play();
task.desynchronize();
end
task.synchronize();
positionalVal.Value += Vector3.new(0,
((positionalVal.Value.Y <= 23000) and 1.5) or 0, -2);
cumulonimbus.CFrame = centerPart.CFrame + positionalVal.Value;
task.desynchronize();
end
end
end
-- A general function that updates the CFrame for instances of the storm
local function updateCFrameDo(): nil -- GOOD
local function cframeAroundMain(instance: part): nil -- GOOD
local positionalVal = instance.positionalVal;
task.synchronize();
instance.CFrame = CFrame.new(centerPart.Position.X + positionalVal.Value.X,
positionalVal.Value.Y, centerPart.Position.Z + positionalVal.Value.Z);
task.desynchronize();
end
for _, folder in pairs(toCFrameFolder:GetChildren()) do
for _, object in pairs(folder:GetChildren()) do
if(object:IsA("Folder")) then
for _, instance in pairs(object:GetChildren()) do cframeAroundMain(instance); end
else cframeAroundMain(object);
end
end
end
end
I tried having them connected in parallel to improve the performance but after a while, the performance reduces and the game drops a few frames. I checked the microprofile and am not sure if anything has changed. Anyone know how I can improve this code? Many thanks! : )