Skip to content

Archived on 2026-10-24. This is a historical implementation note, not current setup instructions or an active task list. Original claims, code examples, file paths, and completion statements have not all been revalidated. Use the current documentation and issue register for maintenance decisions.

Leaderboard UI Refactoring Summary

Overview

Successfully refactored the Leaderboard UI system to follow proper MVC (Model-View-Controller) pattern, consistent with Shop and Collection implementations.

Problems Solved

Before Refactoring:

  1. Mixed Responsibilities: LeaderboardUIController contained both controller logic and view logic
  2. Fragile Code: LeaderboardButton used hardcoded parent/child hierarchy traversal (transform.Find(), GetChild())
  3. Tight Coupling: Direct dependencies between button and controller made code brittle
  4. Difficult Maintenance: UI structure changes would break the button code

After Refactoring:

✅ Clean MVC Separation: Controller, View, and Button have clear responsibilities ✅ Event-Based Communication: Buttons use callbacks instead of direct UI manipulation ✅ No Fragile Hierarchy Traversal: All UI logic encapsulated in LeaderboardView ✅ Easier to Maintain: UI structure changes only affect LeaderboardView ✅ Single Responsibility: Each class has one clear purpose

Architecture Changes

New File: LeaderboardView.cs

Location: Assets/Script/App/UI/Views/LeaderboardView.cs

Responsibilities: - All UI references (loading screen, leaderboard parent, filter texts, etc.) - Building leaderboard list from data - Displaying selected player data - Showing/hiding current player's rank - Managing UI state (loading, filters, navigation)

Key Methods:

- UpdateLoadingUI(bool isActive, string message)
- UpdateFilterText(FilterType type, string text)
- BuildLeaderboardList(LeaderboardData[] data, LeaderboardButton prefab, Action<LeaderboardData> onButtonClicked)
- ShowSelectedPlayerData(LeaderboardData data)
- ShowCurrentRank(bool show, LeaderboardData data, int rank)
- ClearLeaderboardList()
- SetFirstSelected(GameObject firstSelect)

Refactored: LeaderboardButton.cs

Location: Assets/Script/App/UI/Buttons/LeaderboardButton.cs

Changes: - ❌ Removed: ShowData() method with fragile hierarchy traversal - ❌ Removed: Direct access to leaderboardUIControllerObject - ✅ Added: Setup(LeaderboardData data, int rank, Action<LeaderboardData> clickedCallback) method - ✅ Added: OnButtonClick() event handler - ✅ Added: SetCurrentRankData() for "Your Rank" display - Keeps: Own UI references (rankText, nameText, scoreText, difficultyText)

Communication Pattern:

// Button setup
button.Setup(leaderboardData, rankIndex, OnButtonClicked);

// Button click handling
button.OnButtonClick(); // Invokes the callback with LeaderboardData

Refactored: LeaderboardUIController.cs

Location: Assets/Script/App/UI/Controllers/LeaderboardUIController.cs

Changes: - ❌ Removed: All UI references (moved to LeaderboardView) - ❌ Removed: Direct button instantiation logic - ❌ Removed: Data parsing logic (moved to button) - ✅ Added: Reference to LeaderboardView - ✅ Added: leaderboardButtonPrefab for instantiation - ✅ Added: OnLeaderboardButtonClicked() callback handler - ✅ Added: Filter button click handlers (OnDifficultyFilterClicked, etc.)

Responsibilities: - Coordinate between LeaderboardManager and LeaderboardView - Handle user interactions (filter clicks, refresh) - Manage data flow and caching - Delegate UI updates to LeaderboardView

Updated: LeaderboardManager.cs

Location: Assets/Script/External/Network/LeaderboardManager.cs

Changes: - Simplified SpawnLeaderboardCard() coroutine - Removed direct button manipulation - Now delegates UI updates to LeaderboardUIController

Unity Setup Instructions

1. Create LeaderboardView GameObject

  1. Create a new GameObject in your leaderboard menu scene
  2. Name it "LeaderboardView"
  3. Add the LeaderboardView component to it

2. Configure LeaderboardView References

In the Inspector for LeaderboardView, assign all UI references (organized by category in Inspector):

Leaderboard List: - leaderboardParent: Parent Transform where button list spawns - scrollbarAchievement: Scrollbar for navigation

Player Stats Display: - leaderboardGameStatusParent: Parent of player stats display - gameStatusCanvasGroup: CanvasGroup for fading effect on game status panel

Selected Player Info - Basic: - playerNameText: TMP_Text for player name - playerDifficultyText: TMP_Text for difficulty - playerTotalKillText: TMP_Text for total kills - playerLevelText: TMP_Text for level achieved - playerScoreText: TMP_Text for score

Player 1 Stats: - player1NameText: TMP_Text for Player 1 character name - player1StatsContainer: Transform for Player 1 stats (child TMP_Text elements) - player1UpgradesContainer: Transform for Player 1 upgrade icons

Player 2 Stats: - player2Button: Toggle button for Player 2 stats (call LeaderboardView.TogglePlayerStatsPanel() on click) - player2NameText: TMP_Text for Player 2 character name - player2StatsContainer: Transform for Player 2 stats (child TMP_Text elements) - player2UpgradesContainer: Transform for Player 2 upgrade icons

Player Stats Visibility: - player1StatsPanel: GameObject for Player 1 stats panel - player2StatsPanel: GameObject for Player 2 stats panel

Loading Screen: - leaderboardLoadingScreen: Loading screen GameObject - loadingMessageText: TMP_Text for loading message

Filter Texts: - stageText: TMP_Text for stage filter - difficultyText: TMP_Text for difficulty filter - charText: TMP_Text for character filter - versionTextLeaderboard: TMP_Text for version filter

Current Rank Display: - currentRankDisplay: LeaderboardButton component for "Your Rank" display

3. Update LeaderboardUIController

  1. Select your existing LeaderboardUIController GameObject
  2. In the Inspector:
  3. Add a reference to the LeaderboardView GameObject you just created
  4. Add a reference to the leaderboardButtonPrefab (your button prefab)

4. Update Button Prefab

  1. Select your LeaderboardButton prefab
  2. Ensure it has:
  3. LeaderboardButton component
  4. Button component (Unity UI)
  5. TMP_Text components (rankText, nameText, scoreText, difficultyText)
  6. In the Button component's OnClick event:
  7. Add an event
  8. Select the GameObject (the button itself)
  9. Choose LeaderboardButton.OnButtonClick method

5. Update Filter Buttons

For each filter button (Difficulty, Stage, Character, Version, Refresh): 1. Select the button GameObject 2. In the Button component's OnClick event: - Add an event - Select LeaderboardUIController GameObject - Choose appropriate method: - Difficulty: OnDifficultyFilterClicked - Stage: OnStageFilterClicked - Character: OnCharacterFilterClicked - Version: OnVersionFilterClicked - Refresh: OnRefreshClicked

6. Update Player 2 Toggle Button

For the Player 2 toggle button: 1. Select the Player 2 button GameObject 2. In the Button component's OnClick event: - Add an event - Select LeaderboardView GameObject - Choose TogglePlayerStatsPanel() method - This will toggle between Player 1 and Player 2 stats panels when clicked

Data Flow

LeaderboardManager (Model)
    ↓ (Fetches data from internet)
    ↓ (jsonData)
LeaderboardUIController (Controller)
    ↓ (RefreshLeaderboardUI)
    ↓ (passes data & prefab)
LeaderboardView (View)
    ↓ (BuildLeaderboardList)
    ↓ (creates buttons with callbacks)
LeaderboardButton (Button)
    ↓ (OnButtonClick - user clicks)
    ↓ (callback with LeaderboardData)
LeaderboardUIController (Controller)
    ↓ (OnLeaderboardButtonClicked)
    ↓ (passes data)
LeaderboardView (View)
    ↓ (ShowSelectedPlayerData)
    ↓ (updates UI hierarchy)

Benefits

  1. No Fragile Hierarchy Traversal: All UI elements accessed via direct serialized references
  2. Maintainability: UI structure changes only affect LeaderboardView references
  3. Testability: Each component can be tested independently
  4. Reusability: LeaderboardButton follows same pattern as CollectionButton
  5. Scalability: Easy to add new features without breaking existing code
  6. Consistency: Matches Shop and Collection implementation patterns
  7. Robust: Code won't break when UI hierarchy changes

Migration Checklist

  • [x] Create LeaderboardView.cs
  • [x] Refactor LeaderboardButton.cs
  • [x] Refactor LeaderboardUIController.cs
  • [x] Update LeaderboardManager.cs
  • [ ] Create LeaderboardView GameObject in scene
  • [ ] Configure LeaderboardView references
  • [ ] Update LeaderboardUIController references
  • [ ] Update button prefab click events
  • [ ] Update filter button click events
  • [ ] Test in Unity Editor
  • [ ] Test leaderboard data loading
  • [ ] Test button clicks
  • [ ] Test filter functionality
  • [ ] Test current player rank display

Notes

  • The singleton pattern in LeaderboardUIController is preserved for compatibility with LeaderboardManager
  • All existing functionality is preserved, just reorganized
  • The code follows Unity best practices and project conventions
  • Compatible with existing Save system and LeaderboardData structures