Game lagging when tween plays

Have you tried not destroying the tweens immediately after playing? I’m not 100% sure how the internals of replicating the Tween to the clients work, but deleting it so soon on the server may have unintended consequences. The tweens will be garbage collected regardless when you destroy the stand model.

Additionally can you share the client side of the summoning code? Do you hook into RunService.RenderStepped or BindToRenderStep at all on the client?

I never used RunService in any code that is (or is connected to) the summoning code.
I’m probably just dumb, but I don’t think I know what a “client side” is in scripting, so I’ll just send you the LocalScript that triggers the summon.

local Player = game:GetService("Players").LocalPlayer

local rp = game:GetService("ReplicatedStorage")
local summon = rp:WaitForChild("Summon")

local UIS = game:GetService("UserInputService")

local isActive = false
local debounce = false
local cd = 1

UIS.InputBegan:Connect(function(input,isTyping)
	if isTyping then
		return
	elseif input.KeyCode == Enum.KeyCode.Q then
		if debounce == false and isActive == false then
			isActive = true
			debounce = true
			
			summon:FireServer(isActive)
			wait(cd)
			debounce = false
		elseif debounce == false and isActive == true then
			isActive = false
			debounce = true
			
			summon:FireServer(isActive)
			wait(cd)
			debounce = false	
		end
	end
end)

And yes, I tried to not destroy the tweens immediately. I tried to make it wait, I also removed the tween:Destroy() thing, but it didn’t do anything to the lag.

Tweening on serverside is very inefficient and causes server performance to be extremely unstable since you’re updating position, orientation, et cetera 60 times per second on the server side.

Try tweening on clientside for every client, and just update position on serverside roughly like 1 time per second.

4 Likes

I’m kind of new to those things, so I don’t know what to do with that information.
How do I tween on clientside? I don’t even know what clientside is.

Actually, I shouldn’t ask here.

(sorry if im being really dumb, im still not that good at scripting.)

1 Like

You can learn about server-side and client-side here:

Basically, normal Scripts are treated as Server-Side, and LocalScripts are treated as Client-Side.
Server-Side does not have enough performance to process large calculations in a short period while Client-Side does (Client-Side performance depends on your PC’s performance).

Tweening positions and rotations of object(s) costs a lot of performance, and here’s why:

  • It contains lots of information such as; ancestry of the object, goal to be achieved, et cetera.
  • It updates 60 times per second (since ROBLOX is based on 60 FPS, and tweening is meant to be smooth).

As I said above, Server-Side does not have enough performance to hold information that is being received 60 times per second.

To solve this problem, take a look at the quote above. You can tween on Client-Side, which its performance is based on your PC’s performance (MUCH better than Server performance even if it’s not decent).

BUT, if you do the tweening on Client-Side, there goes another problem: The change of information(Position, Rotation, etc) is only applied on Client-Side, not the Server-Side.

You can also solve this problem by lowering the updating frequency of position update and applying to Server(You can simply think it’s tweening, but super laggy).

.
And please don’t be sorry or hesitate to ask things here, everyone’s here to ask and answer questions.

3 Likes

Idk if this will work, what about you make all tweens, insert them in a table, then loop through that table and play them all, then wait a bit and destroy them by doing another for loop on the same table. Try if it works.

1 Like

So, should I put the tweening part of the summon script inside a local script that is inside the summon script?

I’ll try to do that, even though I’m still new to for loops and tables.

Okay, actually, I think it might be because of how many meshes there are. maybe, if I change the meshes to parts, or delete some meshes, I might get a bit less lag.

1 Like

Yes. but I would keep the rest of summon script, and call LocalScript with RemoteEvent to tell LocalScript when to start the tween.

Thanks, that actually is a good idea.

And still it will lag since there would be more than one player in server I guess

By the way, I think you don’t have to call the function Destroy since when the Instance is parented to nil and there are no more reference to it, it will eventually be garbage collected. As far as I know…

Actually, I don’t know what to type in LocalScript.

Should I add the tweens into the LocalScript and then play them when they are meant to be played by using a RemoteEvent, or should I do something else?

Edit: Nevermind, I found out what to do.

Also, where should I put the LocalScript?

Yes, you are far correct.

I prefer placing it in StarterPlayerScripts

For some reason, this happens when I summon it.

This is what it looks like from the explorer:
explorerstandsummonscript

SummonClient’s Code:

local rp = game:GetService("ReplicatedStorage")
local summon = rp:WaitForChild("Summon")
local tween1event = rp:WaitForChild("Tween1")
local tween2event = rp:WaitForChild("Tween2")
local tween3event = rp:WaitForChild("Tween3")
local tween4event = rp:WaitForChild("Tween4")

local TweenService = game:GetService("TweenService")

summon.OnServerEvent:Connect(function(player,isActive)
	local char = player.Character
	local hum = char.Humanoid
	local humRP = char.HumanoidRootPart

	if isActive then
		local stand = script:WaitForChild("StarPlatinumStand"):Clone()

		for _, part in pairs(stand:GetChildren()) do
			if part:IsA("BasePart") then
				part.Transparency = 1
				local weld = Instance.new("ManualWeld")
				weld.Name = "Controller"
				weld.Part0 = stand.PrimaryPart
				weld.Part1 = humRP
				weld.C0 = weld.Part0.CFrame:ToObjectSpace(weld.Part1.CFrame)
				weld.Parent = weld.Part0
			end
		end

				local standhumRP = stand:FindFirstChild("HumanoidRootPart")
				
		tween1event.OnServerEvent:Connect(function()
			for _, part in pairs(stand:GetChildren()) do
				if part:IsA("BasePart") and part ~= standhumRP then
					local goal1 = {}
					goal1.Transparency = 0
					local info = TweenInfo.new(.3)
					local tween1 = TweenService:Create(part,info,goal1)
					tween1:Play()
					tween1:Destroy()
				end
			end
		end)
					
					local stand = char:FindFirstChild("StarPlatinumStand")
					if stand then
						local controller = stand.PrimaryPart:FindFirstChild("Controller")
						if controller then

							local standhumRP = stand:FindFirstChild("HumanoidRootPart")
							tween3event:FireServer()
							for _, part in pairs(stand:GetChildren()) do
								if part:IsA("BasePart") and part ~= standhumRP then
									local goal3 = {}
									goal3.Transparency = 0
									local info = TweenInfo.new(.3)
									local tween3 = TweenService:Create(part,info,goal3)
									tween3:Play()
									tween3:Destroy()
								end
							end
							tween4event:FireServer()
							for _, part in pairs(stand:GetChildren()) do
								if part:IsA("BasePart") and part ~= standhumRP then
									local goal4 = {}
									goal4.Transparency = 1
									local info = TweenInfo.new(.3)
									local tween4 = TweenService:Create(part,info,goal4)
									tween4:Play()
							        tween4:Destroy()

							tween4.Completed:Connect(function()
								stand:Destroy()				
							end)
						end
					end
				end
			end
		end
	end)

Summon’s Code:

local rp = game:GetService("ReplicatedStorage")
local summon = rp:WaitForChild("Summon")
local tween1event = rp:WaitForChild("Tween1")
local tween2event = rp:WaitForChild("Tween2")
local tween3event = rp:WaitForChild("Tween3")
local tween4event = rp:WaitForChild("Tween4")

local TweenService = game:GetService("TweenService")

summon.OnServerEvent:Connect(function(player,isActive)
	local char = player.Character
	local hum = char.Humanoid
	local humRP = char.HumanoidRootPart

	if isActive then
		local stand = script:WaitForChild("StarPlatinumStand"):Clone()
		
		for _, part in pairs(stand:GetChildren()) do
			if part:IsA("BasePart") then
				part.Transparency = 1
			end
		end		
		
				stand.Parent = char
		        stand.PrimaryPart.CFrame = humRP.CFrame
		
		local weld = Instance.new("ManualWeld")
		        weld.Name = "Controller"
				weld.Part0 = stand.PrimaryPart
				weld.Part1 = humRP
				weld.C0 = weld.Part0.CFrame:ToObjectSpace(weld.Part1.CFrame)
				weld.Parent = weld.Part0

				local animControl = stand:FindFirstChild("AnimControl")
				local standhumRP = stand:FindFirstChild("HumanoidRootPart")

				local idle = animControl:LoadAnimation(script.Idle)
				idle:Play()
		
		tween1event:FireServer()
		        for _, part in pairs(stand:GetChildren()) do
			        if part:IsA("BasePart") and part ~= standhumRP then
				        local goal1 = {}
				        goal1.Transparency = 0
				        local info = TweenInfo.new(.01)
				        local tween1 = TweenService:Create(part,info,goal1)
				        tween1:Play()
				        tween1:Destroy()
			        end
		        end
		tween2event:FireServer()
				local goal2 = {}
				goal2.C0 = weld.Part0.CFrame:ToObjectSpace(weld.Part1.CFrame)
				goal2.C1 = weld.Part0.CFrame:ToObjectSpace(weld.Part1.CFrame * CFrame.new(-3,1,2))
		        local info = TweenInfo.new(.3)
				local tween2 = TweenService:Create(weld,info,goal2)
		        tween2:Play()
	        	tween2:Destroy()
			else
		        local stand = char:FindFirstChild("StarPlatinumStand")
		if stand then
			local controller = stand.PrimaryPart:FindFirstChild("Controller")
			if controller then
				
				local standhumRP = stand:FindFirstChild("HumanoidRootPart")
		tween3event:FireServer()
				for _, part in pairs(stand:GetChildren()) do
					if part:IsA("BasePart") and part ~= standhumRP then
						local goal3 = {}
						goal3.Transparency = 0
						local info = TweenInfo.new(.3)
						local tween3 = TweenService:Create(part,info,goal3)
						tween3:Play()
						tween3:Destroy()
					end
				end
		tween4event:FireServer()
				for _, part in pairs(stand:GetChildren()) do
					if part:IsA("BasePart") and part ~= standhumRP then
						local goal4 = {}
						goal4.Transparency = 1
						local info = TweenInfo.new(.3)
						local tween4 = TweenService:Create(part,info,goal4)
						tween4:Play()
						tween4:Destroy()
				
				tween4.Completed:Connect(function()
							stand:Destroy()
						end)
					end
				end
				
			end
		end
    end
end)

Did I do anything wrong?

I have few questions;

  1. Summon being duplicated twice or it being located on the player, which is a problem?
  2. Is the lag issue resolved?

I’m not sure, I haven’t looked into it too much yet.

Yes, it is resolved, according to the microprofiler.