Tweening several projectiles at once is jittery

I have a script which spawns a snowball when the player clicks, there currently isn’t a cooldown for testing purposes which means that there is no limit to how many you can throw at once. When 1-3 snowballs are thrown the motion is fairly smooth but it gets jittery when many are thrown.

Video of the problem:

(Sorry for the potato video quality)

This is the script (Localscript)

local Player = game.Players.LocalPlayer
local UserInputService = game:GetService("UserInputService")
local mouse = Player:GetMouse()
local cooldown = false
UserInputService.InputBegan:Connect(function(input)
	if cooldown == false then
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			cooldown = false
			local camera = game.Workspace.CurrentCamera
			local selectedBall = Player.PlayerGui.Snowball.Value
			print(Player.PlayerGui.Snowball.Value)
			local camCFrame = camera.CFrame
			local projectile = game.ReplicatedStorage:WaitForChild(selectedBall):Clone()
			local weight = projectile.Weight.Value
			local camOrientation = camCFrame-camCFrame.Position;
			local flying
			local impact = game.ReplicatedStorage.ImpactParticle
			local stopper = 1
			local prevCFrame
			local currCFrame
			local RunService = game:GetService("RunService")
			local Table = {}

			for _, Object in ipairs(workspace:GetDescendants()) do
				if Object:IsA("SpawnLocation") then
					table.insert(Table, Object)
				end
			end

			projectile.Parent = workspace.Balls


			projectile.CanCollide = false
			projectile.Position = Vector3.new(Player.Character.HumanoidRootPart.position.X, Player.Character.HumanoidRootPart.position.Y, Player.Character.HumanoidRootPart.position.Z)
			projectile.CFrame = CFrame.new(projectile.Position)*camOrientation
			projectile.Anchored = true
			projectile.CFrame *= CFrame.new(0,1,-2)
			game.ReplicatedStorage.Toss:FireServer(camCFrame, selectedBall)
			
			
			wait(0)

			for i = 1, 2 do
				wait(0)


				local TweenService = game:GetService("TweenService") 

				local Pos = (projectile.CFrame * CFrame.new(0,0,-2.6).Position)-- Change this to the position you want part to move to

				local Moving_Info = TweenInfo.new(
					0.06, --the amount of seconds you want it to take
					Enum.EasingStyle.Quad,
					Enum.EasingDirection.InOut,
					1, --The amount of time you want it to repeat
					false, --Whether you want it to reverse back to the original position when it's done
					0 -- how much time should delay between each repitition
				)

				TweenService:Create(projectile, Moving_Info, {Position = Pos}):Play()
			end
			for i = 1, 3 do
				wait(0)




				local MAX_DISTANCE = 3.9
				local params = RaycastParams.new()
				local Table = {}

				for _, Object in ipairs(workspace:GetDescendants()) do
					if Object:IsA("SpawnLocation") then
						table.insert(Table, Object)
					end
				end
				table.insert(Table, game.Players.LocalPlayer.Character:GetDescendants())
				table.insert(Table,workspace.Balls:GetChildren() )
				params.FilterType = Enum.RaycastFilterType.Blacklist
				params.FilterDescendantsInstances = Table
				local dir = (projectile.Position - (projectile.CFrame * CFrame.new(0,0,-2.6).Position)).Unit * MAX_DISTANCE
				local raycastResult = workspace:Raycast(projectile.Position, dir, params)


				

				if raycastResult ~= nil then
					print(raycastResult.Instance.Name)
				
					local impClone = impact:Clone()
					impClone.Parent = workspace
					impClone.ParticleEmitter.Enabled = true
					impClone.Position = (projectile.CFrame * CFrame.new(0,0,2.3)).Position
					cooldown = false
					projectile:Destroy()
					wait(0.3)
					impClone.ParticleEmitter.Enabled = false
					wait(1)

					impClone:Destroy()
					return

				else
					local TweenService = game:GetService("TweenService") 
			
					local Pos = (projectile.CFrame * CFrame.new(0,0,-2.6).Position)-- Change this to the position you want part to move to

					local Moving_Info = TweenInfo.new(
						0.06, --the amount of seconds you want it to take
						Enum.EasingStyle.Quad,
						Enum.EasingDirection.InOut,
						1, --The amount of time you want it to repeat
						false, --Whether you want it to reverse back to the original position when it's done
						0 -- how much time should delay between each repitition
					)

					TweenService:Create(projectile, Moving_Info, {Position = Pos}):Play()
				end

					
				

			end
			for i = 1, 200 do  --The important part
				wait(0)



				if projectile.Orientation.X < -89 then
					stopper = 0
				else
					stopper = 1
				end


				local MAX_DISTANCE = 3.9
				local params = RaycastParams.new()
				local Table = {}

				for _, Object in ipairs(workspace:GetDescendants()) do
					if Object:IsA("SpawnLocation") then
						table.insert(Table, Object)
					end
				end
				table.insert(Table, game.Players.LocalPlayer.Character:GetDescendants())
				table.insert(Table,workspace.Balls:GetChildren() )
				params.FilterType = Enum.RaycastFilterType.Blacklist
				params.FilterDescendantsInstances = Table
				local dir = (projectile.Position - (projectile.CFrame * CFrame.new(0,0,-2.6).Position)).Unit * MAX_DISTANCE
				local raycastResult = workspace:Raycast(projectile.Position, dir, params)




				if raycastResult ~= nil then
					print(raycastResult.Instance.Name)
					
					
						local impClone = impact:Clone()
					impClone.Parent = workspace
					impClone.ParticleEmitter.Enabled = true
					impClone.Position = (projectile.CFrame * CFrame.new(0,0,2.3)).Position
					cooldown = false
					projectile:Destroy()
					
					wait(0.3)
					impClone.ParticleEmitter.Enabled = false
					wait(1)
					
					impClone:Destroy()
					
					return



				else
					local TweenService = game:GetService("TweenService") 
					projectile.Orientation = Vector3.new(projectile.Orientation.X - 1.3*weight*stopper, projectile.Orientation.Y, projectile.Orientation.Z)
					local Pos = (projectile.CFrame * CFrame.new(0,0,-2.6).Position)-- Change this to the position you want part to move to

					local Moving_Info = TweenInfo.new(
						0.06, --the amount of seconds you want it to take
						Enum.EasingStyle.Quad,
						Enum.EasingDirection.InOut,
						1, --The amount of time you want it to repeat
						false, --Whether you want it to reverse back to the original position when it's done
						0 -- how much time should delay between each repitition
					)

					TweenService:Create(projectile, Moving_Info, {Position = Pos}):Play()
				end
			end
			
			
			projectile:Destroy()
			cooldown = false
			coroutine.yield()
		end
	end
end)

I know this is a lot to look through, thanks in advance.

tweenservice isnt good for projectiles

i suggest you use the FastCast module it will let you create a lot of projectiles with very minimal lag

1 Like

Alright, thank you. I will look into this tomorrow.

I have implemented a new script using fastcast and it seems to be working well, no stuttering. Thanks for the help.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.