TweenService and string.sub lags in game but not in studio?

Alright hello so, i am making an rpg-like game where you can mercy or fight enemies.
Most of the stuff done, and they’re working pretty well on studio, but when I go inside the game, TweenService and string.sub are just much worse than even for loops.

Roblox Studio:
https://gyazo.com/a240c599aae99e6184e92c30e495b851

In-Game:
https://gyazo.com/76bcbe0705a3878e5561da399f13dccd

No, you’re internet isn’t bad while watching In-Game. It’s the game. It’s too laggy. How can I solve this?
If any script needed I can post it here.

Something tells me about that you aren’t using a LocalScript to handle the visuals. It is common that any action done on the server by a player is usually replicated in slight delay.

1 Like

Yes, I am most likely doing it in server. But there’s almost likely nothing to do in client tho. I can only make the loops work in client, but nothing else.

Can you post the script,we cant help with no script

Here, the lag started after doing this function.

	local function OpenFightStuff()
		local Info = TweenInfo.new(1,Enum.EasingStyle.Linear, Enum.EasingDirection.InOut)
		TweenService:Create(Dialogue.DialogueBox.Main.Box, Info, {Transparency = 0}):Play()
		local b = game.Lighting.TakeFightReturn:FireClient(Player)
			local Time = 100
			Dialogue.MainRun.Decal.Transparency = 0
			local Info2 = TweenInfo.new(2,Enum.EasingStyle.Linear, Enum.EasingDirection.InOut)
			local a = TweenService:Create(Dialogue.MainRun, Info2, {CFrame = Dialogue.MainRun.CFrame + Vector3.new(0,0,-15)})
		a:Play()
		local b = coroutine.create(function()

		end)
		coroutine.resume(b)
		if game.Lighting.LoadBattle.Value.Value == false then
			MonsterCharacter.Main.Events.WhenAttacked:Fire(false, Player.CurrentWeapon.Value, Time)
		elseif game.Lighting.LoadBattle.Value.Value == true then
			MonsterCharacter.Main.Events.WhenAttacked:Fire(true, Player.CurrentWeapon.Value, Time)
			a:Cancel()
			wait(0.5)
			game.Lighting.LoadBattle.Value.Value = false
			end
			wait(2)
			TweenService:Create(Dialogue.DialogueBox.Main.Box, Info, {Transparency = 1}):Play()
			Dialogue.MainRun.CFrame = Dialogue.MainBack.CFrame
			Dialogue.MainRun.Decal.Transparency = 1
			TakeAwayTurn()

	end
	
	local Info = TweenInfo.new(1,Enum.EasingStyle.Linear,Enum.EasingDirection.InOut)
	
	local function EndFight(IfMercy)
		if IfMercy == true then
			local back = MonsterCharacter.Main.Events.WhenWon:Invoke(true)
			wait(1)
			if back == "Nothing" then
				if IfMercy == true then
				for i, v in pairs(MonsterCharacter:GetChildren()) do
				if v:IsA("Part") or v:IsA("MeshPart") or v:IsA("UnionOperation") then
				v.Transparency = 0.5
				end
				end
				Player:WaitForChild("Gold").Value = Player:WaitForChild("Gold").Value + Battle:FindFirstChild("Gold").Value
				MonsterCharacter.Main.Sounds.Dust:Play()
				Player.PlayerGui.Music.SoundId = "rbxassetid://0"
					MonsterCharacter.Main.Events.StopAnimation:Fire()
					Player.Gold.Value = Player.Gold.Value + Battle.Gold.Value
				local Texttttt = "You won! You earned 0 XP and "..Battle.Gold.Value.." Gold!"
				for i = 1, #Texttttt do
				wait(0.05)
				Dialogue.MainText.SurfaceGui.Text.Text = string.sub(Texttttt, 1, i)
				end
				wait(2)
				_Battle:Destroy()
				local BlackScreen = Player.PlayerGui:WaitForChild("BlackScreen")
				BlackScreen.Enabled = true
				for i = 1, 10 do
				wait(0.1)
				BlackScreen.Black.BackgroundTransparency = BlackScreen.Black.BackgroundTransparency - 0.1
				end
			    wait(2)
				MonsterCharacter:Destroy()
				FightButton:Destroy()
				ActButton:Destroy()
				ItemButton:Destroy()
				MercyButton:Destroy()
				Dialogue:Destroy()
			    local p = game.Players:GetPlayerFromCharacter(Character)
				Player:LoadCharacter()
				wait(0.5)
				p.Character.HumanoidRootPart.Position = PPosition.Value + Vector3.new(3,0,0)
				wait(0.5)
				wait(0.5)
				PPosition:Destroy()
				BattleMap:Destroy()
				FightFolder:Destroy()
				end
			end
		else
			local back = MonsterCharacter.Main.Events.WhenWon:Invoke(false)
			wait(1)
			if back == "Nothing" then
				if IfMercy == false then
					local suc, fail = pcall(function()
						for i, v in pairs(MonsterCharacter:GetChildren()) do
						if v:IsA("BasePart") or v:IsA("Part") or v:IsA("UnionOperation") then
							v.Anchored = true
						end
						end
					end)

					local suc, fail = pcall(function()
						for i, v in pairs(MonsterCharacter:GetChildren()) do
						if v:IsA("BasePart") or v:IsA("Part") or v:IsA("UnionOperation") then
							TweenService:Create(v, Info, {Transparency = 1}):Play()
						end
						end
					end)
					
					MonsterCharacter.Main.Sounds.Dust:Play()
					FightButton:Destroy()
					ActButton:Destroy()
					ItemButton:Destroy()
					MercyButton:Destroy()
					Player.PlayerGui.Music.SoundId = "rbxassetid://0"
					MonsterCharacter.Main.Events.StopAnimation:Fire()
					Player.XP.Value = Player.XP.Value + Battle.XP.Value
					Player.Gold.Value = Player.Gold.Value + Battle.Gold.Value
					wait(4.5)
					local MegaTextmoment = "You earned "..Battle.XP.Value.." and\n"..Battle.Gold.Value.." Gold!"
					for i = 1, #MegaTextmoment do
						wait(0.05)
						Dialogue.MainText.SurfaceGui.Text.Text = string.sub(MegaTextmoment, 1, i)
					end
					wait(2)
					_Battle:Destroy()
					local BlackScreen = Player.PlayerGui:WaitForChild("BlackScreen")
					BlackScreen.Enabled = true
					for i = 1, 10 do
						wait(0.1)
						BlackScreen.Black.BackgroundTransparency = BlackScreen.Black.BackgroundTransparency - 0.1
					end
					local p = game.Players:GetPlayerFromCharacter(Character)
					Player:LoadCharacter()
					wait(0.5)
					p.Character.HumanoidRootPart.Position = PPosition.Value + Vector3.new(3,0,0)
					wait(0.5)
					wait(0.5)
					PPosition:Destroy()
					BattleMap:Destroy()
					FightFolder:Destroy()
				end
			end
		end
	end

You can use a remote event instead of doing things on the server. The remote can be connected on the client and it can listen for the server firing the event when the tweening needs to be done, so that the client sees it smoothly. It works smoothly in studio since the server is being created on your computer (unless its a team test) so there is little to no delay.

An example of a script that would be laggy for the client is this:

--Server script
local part = game.Workspace:WaitForChild("Part")
local RunService = game:GetService("RunService")

local PART_SPEED_Y = 5

RunService.HeartBeat:Connect(function(deltaTime)
    part.CFrame += CFrame.New(0, deltaTime * PART_SPEED_Y, 0)
end)

Transforming it into something smooth on the client would look like

--Server script
local PART_SPEED_Y = 5

local event = game.ReplicatedStorage.SomeRemoteEvent
event:FireAllClients(PART_SPEED_Y)
--Client script
local RunService = game:GetService("RunService")
local event = game.ReplicatedStorage.SomeRemoteEvent
local part = game.Workspace:WaitForChild("Part")

event.OnServerEvent:Connect(function(speed)
    PART_SPEED_Y = speed
    RunService.HeartBeat:Connect(function(deltaTime)
        part.CFrame += CFrame.New(0, deltaTime * PART_SPEED_Y, 0)
    end)
end)

Hope this helps.

2 Likes

That seems like it will cost me lots of remote event and work, but it’s also the only way I guess.
Thanks!