Absurdly long rendering times when a certain GUI shows in my game

An issue I’ve had in my game I’ve been working on for a few months is that:

Whenever this specific GUI based QTE I have is played, based on how long you’ve been in the server it’ll become unreasonably laggy (frame skips), the longer you’re in the game, the worse they become.

I’ve tried looking through the microprofiler for a solution but the only bar even close to long is just Render and runJob.

Here’s the code for the GUI in question.

game.ReplicatedStorage.Remotes.Fight.DodgeMiniGame.OnClientInvoke = function(blockWindow, dodgeWindow, speed)
	
	local s,e = pcall(function()
		print("Minigame!")
		block.Visible = true
		block.Indicator.Position = UDim2.new(0.01,0,0,0)
		block.Block.Size = UDim2.new(0.10 * blockWindow, 0, 1, 0)
		block.Dodge.Size = UDim2.new(0.015 * dodgeWindow, 0, 1, 0)
		local position = 0.5 + (math.random(0, 2)/10)
		block.Block.Position = UDim2.new(position, 0, 0, 0)
		block.Dodge.Position = UDim2.new(position, 0, 0, 0)
		local blocked 
		local dodged
		local tween = ts:Create(block.Indicator,TweenInfo.new(speed),{Position = UDim2.new(0.96,0,0,0)})
		tween:Play()
		local bind
		local function Stop()
			tween:Pause()
			local blocking = collideservice.isColliding(block.Indicator,block.Block)
			local dodging = collideservice.isColliding(block.Indicator,block.Dodge)
			blocked = blocking
			dodged = dodging
		end

		bind = game:GetService("UserInputService").InputBegan:connect(function(key, gameproccessed)
			if key.KeyCode == Enum.KeyCode.Space then
				Stop()
			end
		end)
		block.Go.MouseButton1Click:Connect(function()
			Stop()
		end)
		tween.Completed:Connect(function()
			blocked = false
			dodged = false
		end)
		repeat wait() until blocked ~= nil and dodged ~= nil
		bind:Disconnect()
		print(blocked)
		print(dodged)
		wait(0.5)
		block.Visible = false
		return {blocked,dodged}
	end)
	
	if s then
		return e[1],e[2]
	else
		warn(e)
		return "Error"
	end
	
end

I should note this happens to all users, and is blatantly obvious that it’s caused by this.

Any help is appreciated.

2 Likes

How often is the remote called? I can see you’re not storing (and so by definition, not disconnecting) the block.Go.MouseButton1Click and tween.Completed connections.

Likely what is happening is that you are not disconnecting the connections you made inside that remote invocation function, which is a term for all the code inside this function:

If you don’t properly disconnect connections which get created regularly, then it will create a memory leak. Stuff is being created all the time which isn’t getting removed, and this takes up a lot of resources.

Maybe it’s just because I’m not familiar with how this script is supposed to work, but I try to keep my connections at the highest scope possible so they’re easier to manage. I would make a global indicatorTween variable, and then when the remote is invoked, your code would look like this:

if indicatorTween then
    indicatorTween:Cancel()
end
indicatorTween = ts:Create(block.Indicator, etc ...)

I would use tween.Completed:Wait() as well, which means

  1. we don’t need an ugly repeat wait() until polling loop (btw, use task.wait)
  2. we don’t need to manage memory, since it yields once until it’s called then the connection is over

*Edit: don’t do the above, since I only realized afterward that you didn’t want to yield the script for the tween. However, the information is still useful.

Finally, always keep connections pertaining to input at the global scope level. At the top of the script, perhaps do something like this:

local indicatorTween
local QTE_Finished = Instance.new("BindableEvent")

function Stop() -- Stop what, exactly? I still don't know
    if indicatorTween then
        indicatorTween:Pause()
    end
    local blocking, dodging -- = collideservice isColliding etc, do this yourself
    QTE_Finished:Fire(blocking, dodging)
end

game:GetService("UserInputService").InputBegan:connect(function(key)
	if key.KeyCode == Enum.KeyCode.Space then
		Stop()
	end
end)

block.Go.MouseButton1Click:Connect(Stop)

In the remote invocation function:

tween.Completed:Once(function()
    QTE_Finished:Fire(false, false)
end)
local blocked, dodged = QTE_Finished.Event:Wait()

I said earlier:

you’re not storing (and so by definition, not disconnecting) the connections

This isn’t entirely true. I just used tween.Completed::Once in that code sample above, and what that does is the same as :Connect, but once it’s called, it’s automatically disconnected, so we don’t have to worry about managing the connection.

Anyway, the way this works is that whichever part of the script fires the QTE_Finished bindable first, “wins.” The winner can be the tween.Completed function, or the input functions at the top of the script.

I would not choose to have a system like this in my game where the server is waiting for client response like that, but I’m saying this as a more experienced scripter so I’m not gonna tell you to scrap all your work or something. I don’t entirely know what you’re trying to accomplish, either. Managing memory can be difficult, though.

1 Like

It’s only fired once to start the QTE, and even after adding disconnects to all our connections, this didn’t fix the issue sadly.

Watch this video, it taught me how to use the MicroProfiler among other things:

You’ll be able to figure out what’s causing the lag, especially with the debug.profilebegin thing.

Post the results here as well

Not enough information to replicate your problem.

1 Like

^ We aren’t sure what the problem could be with the information you provided. What elements does the UI contain (eg. Frame, TextLabel, etc)?

What you described sounds like a memory leak, though.

Are you sure? Try disabling the script, and see if anything changes.

1 Like

I’m back, and disabling it wouldn’t matter cause this is what I’m trying to debug currently. It’s a remotefunction that fires to this qte to show it and track it, then return if you timed it correctly.
image
This is all that’s inside the UI. And yeah it seems like a memory leak as it gets worse the longer you stay in the game.

I’ve tried using the microprofiler tutorial that @GFink posted, but even using debug.profilebegin it’s not visible and still just appears as a massive line on render and runjob. Using performance stats I can see a noticable spike in cpu usage when the lag spike happens though.

Edit: I just looked further and saw some code related to it that might be part of it.


This is where those bindable events on indicator are created, wonder if this is causing it?

OK I figured it out, it was that collisiongroup thing, it was essentially unused and removing it fixed the lag issue. Guess it’s just related to that module we use for gui collisions. Thanks all who tried to help though.

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