Need help with custom badge system

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.

1 Like

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. :slight_smile:

1 Like

Tysm!
I knew the solution was probably very simple because I’m quite dumb :sob:
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.

This topic has already been solved - there’s no need to reply unless you have something to add to the existing soultion.

If I wanted to ask ChatGPT, I would’ve done so already, thanks.