How to run multiple tweens at the same time in a while loop

Hey, I am having a problem, I’ve created a script that creates a balloon that flies around the map! The way the balloon works is there are some parts called “Points” around the map (This is a tower defense game), and a balloon tweens to them one after another. But, when I put it in a while loop, it waits for the fist balloons tweens to finish and then creates another one. I got an idea on how to bypass it, but it is very in-efficient. The way I did it is:

  1. Created an IntValue (let’s call it "SendBalloons)
  2. Made a while loop that increases the Value of SendBalloons every 0.1 second
  3. Created a .Changed event that fires a balloon every time the SendBalloons get changed.

And it works, but it is a LOT of job for a single wave. Imagine wave number 99: I will have 100 different balloons, which means I will have 100 .Changed events and 100 while loops! (Because I want to fire a different amount of balloons)

So, my question is:

  • How do I change my script in a way so that the while loop would work with my balloon?

This is the module script:

local timeToP1and3 = 86;
local timeToP2 = 113;
local timeToP4 = 113;
local timeToP5 = 31;
local timeToP6 = 65.5;
local timeToP7 = 106.25;
local timeToP8 = 225.75;
local points = game.Workspace.Map.Points
local tweenServ = game:GetService("TweenService")
-- VARIABLES
local tweeningInfo8 = TweenInfo.new(
	timeToP8, -- TIME
	Enum.EasingStyle.Linear, -- STYLE
	Enum.EasingDirection.InOut, -- DIRECTION		EIGHT TWEEN INFO
	0, -- REAPEAT THIS MANY TIMES
	false, -- SHOULD IT REPEAT 
	0
)
local tweenGoal1 = {
	Position = points.Point1.Position
}
local tweenGoal2 = {
	Position = points.Point2.Position
}
local tweenGoal3 = {
	Position = points.Point3.Position
}
local tweenGoal4 = {
	Position = points.Point4.Position
}
local tweenGoal5 = {
	Position = points.Point5.Position
}
local tweenGoal6 = {
	Position = points.Point6.Position
}
local tweenGoal7 = {
	Position = points.Point7.Position
}
local tweenGoal8 = {
	Position = points.EndPosition.Position
}

local redBalloon = {
	new = function()
		return{
			ballonNameInRS = "RedBalloon";
			speed = 0.2;  -- ORIGINAL 0.2
			DamageValue = 1;
			MoneyCost = 1;
			IncomeIncrease = 0.1;
			create = function(self)
				local newBalloon = game:GetService("ReplicatedStorage").Balloons:WaitForChild(self.ballonNameInRS):Clone();
				newBalloon.Name = self.ballonNameInRS;
				newBalloon.Position = game.Workspace.Map.Points.StartPosition.Position;
				newBalloon.Parent = game.Workspace.OnGoingBalloonsTeam1;
				newBalloon.ClickDetector.MouseClick:Connect(function(player)
					self.DamageValue = self.DamageValue - player.PlayersDamage.Value
					if self.DamageValue == 2 then
						newBalloon.BrickColor = BrickColor.new("Toothpaste")
					end
					if self.DamageValue == 1 then
						newBalloon.BrickColor = BrickColor.new("Really red")
					end
					if self.DamageValue <= 0 then
						player.Income.Value = player.Income.Value + self.IncomeIncrease
						newBalloon:Destroy()
					end
				end)
				local tweeningInfo1and3 = TweenInfo.new(
					timeToP1and3*self.speed, -- TIME
					Enum.EasingStyle.Linear, -- STYLE
					Enum.EasingDirection.InOut, -- DIRECTION			ONE AND THREE TWEEN INFO
					0, -- REAPEAT THIS MANY TIMES
					false, -- SHOULD IT REPEAT 
					0
				)
				local tweenP = tweenServ:Create(newBalloon,tweeningInfo1and3,tweenGoal1)
				tweenP:Play()
				tweenP.Completed:Wait()
				newBalloon.CFrame = CFrame.new(newBalloon.Position) * CFrame.Angles(0, math.rad(90), 0)
				--
				local tweeningInfo2 = TweenInfo.new(
					timeToP2*self.speed, -- TIME
					Enum.EasingStyle.Linear, -- STYLE
					Enum.EasingDirection.InOut, -- DIRECTION			TWO TWEEN INFO
					0, -- REAPEAT THIS MANY TIMES
					false, -- SHOULD IT REPEAT 
					0
				)
				local tweenP = tweenServ:Create(newBalloon,tweeningInfo2,tweenGoal2)
				tweenP:Play()
				tweenP.Completed:Wait()
				newBalloon.CFrame = CFrame.new(newBalloon.Position) * CFrame.Angles(0, math.rad(0), 0)
				--
				local tweeningInfo1and3 = TweenInfo.new(
					timeToP1and3*self.speed, -- TIME
					Enum.EasingStyle.Linear, -- STYLE
					Enum.EasingDirection.InOut, -- DIRECTION			ONE AND THREE TWEEN INFO
					0, -- REAPEAT THIS MANY TIMES
					false, -- SHOULD IT REPEAT 
					0
				)
				local tweenP = tweenServ:Create(newBalloon,tweeningInfo1and3,tweenGoal3)
				tweenP:Play()
				tweenP.Completed:Wait()
				newBalloon.CFrame = CFrame.new(newBalloon.Position) * CFrame.Angles(0, math.rad(-90), 0)
				--
				local tweeningInfo4 = TweenInfo.new(
					timeToP4*self.speed, -- TIME
					Enum.EasingStyle.Linear, -- STYLE
					Enum.EasingDirection.InOut, -- DIRECTION			FOUR TWEEN INFO
					0, -- REAPEAT THIS MANY TIMES
					false, -- SHOULD IT REPEAT 
					0
				)
				local tweenP = tweenServ:Create(newBalloon,tweeningInfo4,tweenGoal4)
				tweenP:Play()
				tweenP.Completed:Wait()
				newBalloon.CFrame = CFrame.new(newBalloon.Position) * CFrame.Angles(0, math.rad(180), 0)
				--
				local tweeningInfo5 = TweenInfo.new(
					timeToP5*self.speed, -- TIME
					Enum.EasingStyle.Linear, -- STYLE
					Enum.EasingDirection.InOut, -- DIRECTION			FIVE TWEEN INFO
					0, -- REAPEAT THIS MANY TIMES
					false, -- SHOULD IT REPEAT 
					0
				)
				local tweenP = tweenServ:Create(newBalloon,tweeningInfo5,tweenGoal5)
				tweenP:Play()
				tweenP.Completed:Wait()
				newBalloon.CFrame = CFrame.new(newBalloon.Position) * CFrame.Angles(0, math.rad(-90), 0)
				--
				local tweeningInfo6 = TweenInfo.new(
					timeToP6*self.speed, -- TIME
					Enum.EasingStyle.Linear, -- STYLE
					Enum.EasingDirection.InOut, -- DIRECTION			SIX TWEEN INFO
					0, -- REAPEAT THIS MANY TIMES
					false, -- SHOULD IT REPEAT 
					0
				)
				local tweenP = tweenServ:Create(newBalloon,tweeningInfo6,tweenGoal6)
				tweenP:Play()
				tweenP.Completed:Wait()
				newBalloon.CFrame = CFrame.new(newBalloon.Position) * CFrame.Angles(0, math.rad(0), 0)
				--
				local tweeningInfo7 = TweenInfo.new(
					timeToP7*self.speed, -- TIME
					Enum.EasingStyle.Linear, -- STYLE
					Enum.EasingDirection.InOut, -- DIRECTION			SEVEN TWEEN INFO
					0, -- REAPEAT THIS MANY TIMES
					false, -- SHOULD IT REPEAT 
					0
				)
				local tweenP = tweenServ:Create(newBalloon,tweeningInfo7,tweenGoal7)
				tweenP:Play()
				tweenP.Completed:Wait()
				newBalloon.CFrame = CFrame.new(newBalloon.Position) * CFrame.Angles(0, math.rad(90), 0)
				--
				local tweeningInfo8 = TweenInfo.new(
					timeToP8*self.speed, -- TIME
					Enum.EasingStyle.Linear, -- STYLE
					Enum.EasingDirection.InOut, -- DIRECTION		EIGHT TWEEN INFO
					0, -- REAPEAT THIS MANY TIMES
					false, -- SHOULD IT REPEAT 
					0
				)
				local tweenP = tweenServ:Create(newBalloon,tweeningInfo8,tweenGoal8)
				tweenP:Play()
				tweenP.Completed:Wait()
				game.Workspace.HealthPointsTeam1.Value = game.Workspace.HealthPointsTeam1.Value - self.DamageValue
				newBalloon:Destroy()
				--
			end
		}
	end
}

return redBalloon

And here is the script with the while loop and a screenshot of what happens when I run it:

local redBalloon1 = require(game.ReplicatedStorage.RedBalloonScriptTeam1)

while wait(0.01) do
      local rb1 = redBalloon1.new()
      rb1:create()
end

BTW, sorry if there are some newbie mistakes - I very new to scripting, started 2 months ago.

In the loop script, would spawning a function be useful in creating this effect?

local redBalloon1 = require(game.ReplicatedStorage.RedBalloonScriptTeam1)

while wait(0.01) do
      spawn(function()
            local rb1 = redBalloon1.new()
            rb1:create()
      end)
end
3 Likes