Hello! I’m trying to make a custom badge system and so it was going really good until I had to start working with GUI.
I want this screen to display the info of the badge you had just clicked on.
However, it will only display the “first badge” no matter which one I press.
I tried to make a script that would check if the badge you just clicked on is one of the badges you own but it would display the badges I don’t own anyway and it wasn’t until I tried a very convoluted way of going about it by checking one of the UI elements visibility that it would finally not try to display badges I don’t own.
However, upon adding the “secret badge” to my profile it still displays the “first badge” when i click on it.
The way this screen works is whenever the player clicks the button on the left of the screen it clones the “slotTemplate” into the “badgesScreen” where it is displayed. This is repeated for every badge in the game.
Each slot has a local script inside that is supposed to display the description.
This is the inside of ShowDesc
local UserInputService = game:GetService("UserInputService")
local BadgeService = require(game:GetService("ReplicatedStorage").BadgeService) -- the module that stores all the badges in the game and retrieves all the info about the badge as an array of strings
local showDesc = game:GetService("ReplicatedStorage").events.ShowDesc
local slot = script.Parent
local detailsScreen = game:GetService("Players").LocalPlayer.PlayerGui.ScreenGui.badgeDetailsScreen
local badgesScreen = game:GetService("Players").LocalPlayer.PlayerGui.ScreenGui.badgesScreen
local exitButton = detailsScreen.exitButton
slot.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 and slot.locked.Visible == false then
showDesc:FireServer() -- a server script retrieves the player's saved data from a module and returns it
end
end)
showDesc.OnClientEvent:Connect(function(badges, ownedBadges)
if table.find(ownedBadges, slot.id.Value) then -- the part that doesnt work
local info = BadgeService.GetBadgeInfo(slot.id.Value)
detailsScreen.title.Text = info.name
detailsScreen.description.Text = info.desc
detailsScreen.thumbnail.Image = info.thumbnailId
detailsScreen.Visible = true
badgesScreen.Visible = false
end
end)
exitButton.MouseButton1Click:Connect(function()
detailsScreen.Visible = false
badgesScreen.Visible = true
end)
I was thinking that it’s because I have this script in every frame and the script runs even if the frame that was pressed isn’t it’s parent?
Please help me. I’ve been struggling with this for so long already and it seems that I’ve tried everything I could think of.
If ShowDesc is in each of your slots, they will both receive the OnClientEvent, causing this behavior. You’ll need a way to tell if the incoming event is for the badge you’ve clicked on. Since you don’t really need all the ownedBadges returned, just pass the badge that was requested back to the client. You’ll need to send the slot.id.Value to the server and then have the server return it back to the client if they actually own it. There’s definitely a better way to handle this system overall however, that will cause me to dive into the controller-service architecture along with some MVC patterns. What I said should fix the issue though. Let me know if it helps.
Tysm!
I knew the solution was probably very simple because I’m quite dumb
And yeah, there’s definitely a better way to handle this system but I was never quite smart in this field, so it is what it is.
The issue you’re describing is a classic scope problem with your LocalScript references. When you clone the slotTemplate multiple times, each clone’s LocalScript is trying to reference UI elements that either don’t exist in its hierarchy or are being shared across all instances.Here’s what’s likely happening:**The Problem:**Each cloned slot’s LocalScript is probably referencing a global badgeInfo display frame instead of finding the correct badge data. When you click any badge, the script updates the same shared UI element with whatever data it finds first.**The Solution:**Structure your code so each cloned slot only manages its own data:1. Pass badge data through the clone itself. Instead of having the LocalScript search for badge info, store it directly on the cloned instance as a Value object:lualocal badgeClone = template:Clone()local badgeData = Instance.new("StringValue")badgeData.Name = "BadgeID"badgeData.Value = badgeIdbadgeData.Parent = badgeClonebadgeClone.Parent = badgesScreen2. Reference this data in your LocalScript:lualocal badgeId = script.Parent:WaitForChild("BadgeID").Value-- Now fetch and display only THIS badge's info3. Verify the display frame is unique. Make sure your info display isn’t being shared. Each badge click should update an independent info panel, not a global one.The “convoluted workaround” with visibility checks suggests you were fighting this exact problem—you shouldn’t need that if your data binding is correct.Test by clicking different badges and checking what badgeId value the script actually reads. If all slots are reading the same value, your cloning/data-passing logic needs adjustment.