I created a title system for my current project, but it seems very performance intensive when playing. Is there anyway I could optimize this script?
Main Title Script (LocalScript):
local GPD = game.ReplicatedStorage.GetPlayerData
local TEE = game.ReplicatedStorage.TitleEquipEvent
local plr = game.Players.LocalPlayer
local function deactivateTitles(exception)
for _,v in pairs(script.Parent:GetChildren()) do
if v:IsA("Frame") and v.Name ~= exception then
local actButton = v:FindFirstChild("ActivateButton")
actButton.BackgroundColor3 = Color3.fromRGB(255, 0, 0)
actButton.Text = 'OFF'
end
end
end
local function confirmRequirements(reqText)
local requirement , requirementType
local child
for _,v in pairs(reqText:GetChildren()) do
child = v
break
end
requirement = child.value
requirementType = child.Name
return requirement , requirementType
end
local badgeService = game:GetService("BadgeService")
local function checkPlayerRequirements(requirementType , requirement)
if requirementType == 'Badge' then
return badgeService:UserHasBadgeAsync(plr.UserId, requirement)
elseif requirementType == 'Wins' then
return plr.leaderstats.Wins.Value >= requirement
else
local playerData = GPD:InvokeServer(requirementType) --ask server for playerdata (stored in serverstorage)
return playerData >= requirement
end
end
local function addTitle(title , requirementType , requirement)
local playerData = checkPlayerRequirements(requirementType , requirement)
if playerData then
TEE:FireServer(true , title)
return
end
end
local function setOwned(owned , title) --to avoid duplicating 10+ lines of code to check when gui is opened
if owned then
title.Owned.Text = 'Owned'
title.Owned.TextColor3 = Color3.fromRGB(0, 255, 127)
else
title.Owned.Text = 'Not Owned'
title.Owned.TextColor3 = Color3.fromRGB(170, 61, 61)
end
end
task.wait(2)
for _,v in pairs(script.Parent:GetChildren()) do
if v:IsA("Frame") then
local actButton = v:FindFirstChild("ActivateButton")
local title = v.Name
local requirementText = v.Requirement
local requirement , requirementType = confirmRequirements(requirementText)
local owned = checkPlayerRequirements(requirementType, requirement)
setOwned(owned , v)
actButton.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
if actButton.BackgroundColor3 == Color3.fromRGB(255, 0, 0) then
local canAfford = checkPlayerRequirements(requirementType, requirement) --checks requirements again (might cause performance issues)
if canAfford then
addTitle(title, requirementType, requirement)
else return end
actButton.BackgroundColor3 = Color3.fromRGB(0, 255, 0)
actButton.Text = "ON"
deactivateTitles(title)
else
actButton.BackgroundColor3 = Color3.fromRGB(255, 0, 0)
actButton.Text = 'OFF'
TEE:FireServer(false , title)
end
end
end)
end
end
script.Parent.Parent.TitleButton.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
for _,v in pairs(script.Parent:GetChildren()) do
if v:IsA("Frame") then
local requirementText = v.Requirement
local requirement , requirementType = confirmRequirements(requirementText)
local owned = checkPlayerRequirements(requirementType, requirement)
setOwned(owned , v)
end
end
end
end)
Here’s the script on the other end of the server invoke. I need this because most, if not all, player data is stored in ServerStorage.
local GPD = game.ReplicatedStorage.GetPlayerData
local playerDataFolder = game.ServerStorage.PlayerData
GPD.OnServerInvoke = function(player , requestedData)
local pd = playerDataFolder:FindFirstChild(player.Name.."_valuefolder")
local data
for _,v in pairs(pd:GetDescendants()) do
if v.Name == requestedData then
data = v.Value
return data
end
end
end
Finally, this is the script that applies the title (probably not needed in this case, but I’ll show it anyway):
local TEE = game.ReplicatedStorage.TitleEquipEvent
local SCE = game.ReplicatedStorage.ServerCosmeticEvent
local TitleFolder = game.ServerStorage.Titles
local playerDataFolder = game.ServerStorage.PlayerData
local function AddTitle(player, add , title)
local char = player.Character
local head = char.Head
for _,v in pairs(head:GetChildren()) do
if v:IsA("BillboardGui") then
v:Destroy()
end
end
if add then
local newTitle = TitleFolder:FindFirstChild(title):Clone()
newTitle.Parent = head
playerDataFolder[player.Name.."_valuefolder"].CurrentCosmetics.Title.Value = title
TEE:FireClient(player , true , title)
else
TEE:FireClient(player , false , title)
playerDataFolder[player.Name.."_valuefolder"].CurrentCosmetics.Title.Value = ''
end
end
TEE.OnServerEvent:Connect(AddTitle)
SCE.Event:Connect(function(player , cosmeticType , cosmeticName)
if cosmeticType == 'Title' and cosmeticName and cosmeticName ~= '' and cosmeticName ~= ' ' then
AddTitle(player , true , cosmeticName)
end
end)
Some screenshots of the explorer:
How player data is stored on the server (each folder is created when the play joins):
Here’s what the gui looks like:
It can get delayed by up to a second sometimes when equipping a title. It’s instant when turning it off though.
Again, I was just wondering it there was anything I could do to optimize the main script. Maybe there’s a better way to make a title system.
Thanks for your help in advance!