Gui and its scripts is really affecting the performance of my game

I realized that my game gets really laggy after staying in a server for a while and noticed that there’s a really big amount of things being sent and recieved on the client. I looked into it and noticed the presence of the shop gui makes a really big difference. Does anyone know how i can optimize the scripts inside?

–with shop gui in the game

–after deleting shop gui

theres a variety of things being done in the shop and i feel the remote events are a large reason for this happening.

in the shop you can:

-buy badges with leaderstats
-buy a case with leaderstats
-buy abilities with leaderstats

the badges section uses a total of seven remote events. i know it’s alot, i didn’t code this part of the game but looking into it i don’t see an alternative.

–badges section

–this is what goes on in the buy buttons

local BadgeService = game:GetService("BadgeService")
local RemoteEvent = game.ReplicatedStorage.Remotes:WaitForChild("b1Event")
local button = script.Parent
local playerKills = game.Players.LocalPlayer.leaderstats["K-Points"]
local playerWins = game.Players.LocalPlayer.leaderstats["W-Points"]

if BadgeService:UserHasBadgeAsync(game.Players.LocalPlayer.UserId, 523832810294129) then
	button.Text = "Owned"
	button.TextColor3 = Color3.fromRGB(248, 248, 248)
	button.BackgroundColor3 = Color3.fromHex("00FF90")
	button.Parent.UIStroke.Color = Color3.fromRGB(0, 229, 126)
end

button.Activated:Connect(function()
	if playerKills.Value >= 50 and playerWins.Value >= 10 and button.Text ~= "Owned" then
		RemoteEvent:FireServer()
		button.Text = "Owned"
		button.TextColor3 = Color3.fromRGB(248, 248, 248)
		button.BackgroundColor3 = Color3.fromHex("00FF90")
		button.Parent.UIStroke.Color = Color3.fromRGB(0, 229, 126)
	end
end)

Next up is the cases section.

–case section

–script used when pressing buy (theres two of these for both of the leaderstats)

local button = script.Parent
local remote = game.ReplicatedStorage.Remotes.CaseEvent
local case = button.Parent.Parent.Parent
local caseData = require(game.ReplicatedStorage.Cases[case.Name].CaseData)
local player = game.Players.LocalPlayer
local debounce = true

button.Activated:Connect(function()
	if debounce then
		debounce = false
		if caseData:CaseValidity(player, "K") then
			remote:FireServer(case.Name, "K")
			case.Visible = false
		end
		debounce = true
	end		
end)

with these cases there’s also a module script that contains all the data of the case, potentially may be the cause im not sure.

–module script

local CaseData = {}

CaseData.KPointPrice = 10

CaseData.WPointPrice = 5

function CaseData:CaseValidity(player, priceType)
	local leaderstats = player.leaderstats
	local price
	local playerPointValue
	if priceType == "K" then
		price = CaseData.KPointPrice
		playerPointValue = leaderstats["K-Points"].Value
	elseif priceType == "W" then 
		price = CaseData.WPointPrice
		playerPointValue = leaderstats["W-Points"].Value
	elseif priceType == nil then
		error("Missing argument \"priceType\"")
	else
		error("Invalid \"priceType\" provided")
	end
	
	if playerPointValue >= price then
		return true
	else
		return false
	end
end

CaseData.Rarities = {

	["Common"] = {
		Rarity = {Name = "Common", Chance = 0.5, Color = Color3.fromRGB(80, 80, 80)},
		Items = {

			{Name = "White Lumen", ImageId = 17831234430, SwordId = 8}
		}
	},
	["Uncommon"] = {
		Rarity = {Name = "Uncommon", Chance = 0.3, Color = Color3.fromRGB(58, 237, 160)},
		Items = {

			{Name = "Green Lumen", ImageId = 17831239204, SwordId = 10},
			{Name = "Black Lumen", ImageId = 17831236720, SwordId = 9}
		}
	},
	["Rare"] = {
		Rarity = {Name = "Rare", Chance = 0.15, Color = Color3.fromRGB(65, 216, 253)},
		Items = {

			{Name = "Blue Lumen", ImageId = 17831244719, SwordId = 12},
			{Name = "Orange Lumen", ImageId = 17831246768, SwordId = 11}
		}
	},
	["Epic"] = {
		Rarity = {Name = "Epic", Chance = 0.04, Color = Color3.fromRGB(91, 55, 250)},
		Items = {

			{Name = "Red Lumen", ImageId = 17831264669, SwordId = 13},
			{Name = "Purple Lumen", ImageId = 17831256668, SwordId = 14}
		}
	},
	["Legendary"] = {
		Rarity = {Name = "Legendary", Chance = 0.01, Color = Color3.fromRGB(254, 204, 48)},
		Items = {

			{Name = "Prismatic Lumen", ImageId = 17831266034, SwordId = 15}
		}
	}
}

function CaseData:GetRarity(specifiedRarity)
	local rarities = {}

	if CaseData.Rarities[specifiedRarity] then
		table.insert(rarities, CaseData.Rarities[specifiedRarity])
	else
		error("Missing valid argument \"specifiedRarity\"")
	end

	return rarities
end

function CaseData:GetAllRarities()
	local rarities = CaseData.Rarities
	
	for groupName, group in pairs(rarities) do
		for i, item in pairs(group.Items) do
			item.GroupName = groupName
		end
	end
	
	return rarities
end

return CaseData

finally there’s one more script which looking into it i guess awards the sword you rolled? i feel like alot of these scripts are unnecessary.

–the script

local cases = game.ReplicatedStorage.Cases
local remote = game.ReplicatedStorage.Remotes.CaseEvent
local swordValMod = require(game.ReplicatedStorage.ModuleScripts.SwordValues)
local swordValues = swordValMod.SwordValues

remote.OnServerEvent:Connect(function(plr, caseName, priceType)
	local case = game.ReplicatedStorage.Cases[caseName]
	local caseData = require(case.CaseData)
	local rarities = caseData.Rarities
		
	if caseData:CaseValidity(plr, priceType) then
		if priceType == "K" then
			plr.leaderstats["K-Points"].Value -= caseData.KPointPrice
		elseif priceType == "W" then
			plr.leaderstats["W-Points"].Value -= caseData.WPointPrice
		elseif priceType == "D" then
			plr.leaderstats["D-Points"].Value -= caseData.DPointPrice
		elseif priceType == "H24" then
			plr["H24-Points"].Value -= caseData.H24PointPrice
		end
		
		local cyclingItems = {}
		for i = 1, 28 do
			local caseRoll = math.random()
			local cumulativeChance = 0
			local rarityGroup
			local groupName

			for name, group in pairs(rarities) do
				local chance = group.Rarity.Chance
				cumulativeChance += chance

				if caseRoll <= cumulativeChance then
					rarityGroup = group
					groupName = name
					break
				end
			end

			if #rarityGroup.Items > 1 then
				local itemIndex = math.random(1, #rarityGroup.Items)
				local caseItem = rarityGroup.Items[itemIndex]
				caseItem.RarityGroup = groupName

				table.insert(cyclingItems, caseItem)
			else
				rarityGroup.Items[1].RarityGroup = groupName
				table.insert(cyclingItems, rarityGroup.Items[1])
			end
		end
		
		local winningId = 23
		local winningItem = cyclingItems[winningId]
		
		local inventory = plr.Inventory
		local newSword = Instance.new("NumberValue")
		newSword.Name = winningItem.SwordId
		newSword.Value = winningItem.SwordId
		newSword.Parent = inventory
		
		remote:FireClient(plr, cyclingItems, winningId, case)
	end
end)

The last part of the shop is the abilities section.

–the section

after you press an ability it asks you do you want to purchase and uses this code:

–the code

local button = script.Parent
local remote = game.ReplicatedStorage.Remotes.AbilityFunction
local Event = game.ReplicatedStorage.Remotes.AbilityEvent
local ability = button.Parent.Parent
local abilityButton = ability.Parent.Parent.AbilitiesFrame[ability.Name][ability.Name .. "Icon"].ImageButton
local player = game.Players.LocalPlayer
local abilityValMod = require(game.ReplicatedStorage.ModuleScripts.AbilityValues)
local abilityValues = abilityValMod.AbilityValuesId
local abilityValue = abilityValues[button.Parent.Parent.Name]
local debounce = true

button.Activated:Connect(function()
	if debounce then
		if player.leaderstats["K-Points"].Value >= tonumber(ability.KPrice.Text) and player.leaderstats["W-Points"].Value >= tonumber(ability.WPrice.Text) then
			debounce = false
			if remote:InvokeServer(ability.Name, tonumber(ability.KPrice.Text), tonumber(ability.WPrice.Text)) then
				abilityButton.BackgroundColor3 = Color3.fromRGB(0, 255, 144)
				abilityButton.Parent.BorderColor3 = Color3.fromRGB(0, 229, 126)
				abilityButton.Parent.Parent.PriceTag.BackgroundColor3 = Color3.fromRGB(0, 255, 144)
				abilityButton.Parent.Parent.PriceTag.BorderColor3 = Color3.fromRGB(0, 229, 126)
				
				local bought = Instance.new("StringValue")
				bought.Name = "Bought"
				bought.Parent = abilityButton.Parent.Parent

				for i, child in pairs(abilityButton.Parent.Parent.PriceTag:GetChildren()) do
					child:Destroy()
				end

				local ownedText = game.ReplicatedStorage.UiElements.OwnedText:Clone()
				ownedText.Parent = abilityButton.Parent.Parent.PriceTag
				ownedText.Text = "Owned"
				ownedText.Size = UDim2.new(0.6, 0,0.6, 0)
				ownedText.Position = UDim2.new(0.5, 0, 0.5, 0)
				
				Event:FireServer(abilityValue)

				for i, frame in pairs(ability.Parent.Parent.AbilitiesFrame:GetChildren()) do
					if frame:IsA("Frame") and frame.PriceTag:FindFirstChild("OwnedText") then
						if frame[frame.Name .. "Icon"].ImageButton.EquippedText.Text == "Equipped" and frame[frame.Name .. "Icon"].ImageButton ~= abilityButton then
							frame[frame.Name .. "Icon"].ImageButton.EquippedText.Text = ""
						end
					end
				end
				
				abilityButton.EquippedText.Text = "Equipped"
				
				local newScript = game.ReplicatedStorage.LocalScripts.AbilityButtonScript:Clone()
				newScript.Parent = abilityButton
				
				local pScript = abilityButton:FindFirstChild("PromptScript")
				if pScript then
					pScript:Destroy()
				end
				
				ability.Visible = false
			end
			task.delay(0.25, function()
				debounce = true
			end)
		end
	end
end)

final things i want to share. I’ve looked into this code and i’m not really sure how to find an alternative to what it’s doing… i would also appreciate any other tips to improve performance.

2 Likes

Why not just use 1 remote where you pass in the data you want to validate/ buy

2 Likes

i can see how i could do that with the badges but for the rest i’m not really sure. the code was written so weirdly to me i can’t really pick up off it. any ideas?

2 Likes