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.

Manager Refactoring Summary

Overview

This document summarizes the refactoring of the App/Managers folder, converting singleton-style managers to static classes and reorganizing the codebase for better architecture.

Date

December 29, 2025

Changes Made

1. Converted Managers to Static Classes

The following managers have been converted from singleton-style (using .Instance) to static classes:

ShopManager

  • Path: Assets/Script/App/Managers/ShopManager.cs
  • Changes:
  • Removed Instance property
  • Changed all instance methods to static methods
  • Made shopUpgradesList private static
  • Added Initialize() method for setup
  • Added GetShopUpgrades() public method for data access
  • Made LoadDataShop() public (was private)

Old usage: ShopManager.Instance.BuyUpgrade(type) New usage: ShopManager.BuyUpgrade(type)

AchievementManager

  • Path: Assets/Script/App/Managers/AchievementManager.cs
  • Changes:
  • Removed Instance property
  • Changed all instance methods to static methods
  • Made achievements and popupQueue private static
  • Added Initialize() method for setup
  • Added GetPopupQueue() public method for UI access
  • Added IsAchievementLoaded public static property

Old usage: AchievementManager.UpdateAchievementProgress(id) New usage: AchievementManager.UpdateAchievementProgress(id)

InputManager

  • Path: Assets/Script/App/Managers/InputManager.cs
  • Changes:
  • Removed Instance property
  • Changed all instance methods to static methods
  • Made all data fields private static
  • Added Initialize() method for setup with multiple parameters
  • Made IsKeyReady public static property

Old usage: InputManager.GetKeyDownKeyboard("Back", 0) New usage: InputManager.GetKeyDownKeyboard("Back", 0)

LocalizationManager

  • Path: Assets/Script/App/Managers/LocalizationManager.cs
  • Changes:
  • Removed Instance property
  • Changed all instance methods to static methods
  • Made buttons private static
  • Added Initialize() method for setup
  • Created CoroutineRunner singleton helper for coroutine support

Old usage: LocalizationManager.Instance.ChangeLocale(0) New usage: LocalizationManager.ChangeLocale(0)

CollectionManagerRefactored

  • Path: Assets/Script/App/Managers/CollectionManagerRefactored.cs
  • Changes:
  • Converted to static class
  • Removed Instance property
  • Changed all instance methods to static methods
  • Made characters and enemies private static
  • Added Initialize() method for setup

Old usage: CollectionManagerRefactored.Instance.GetAvailableCharacters() New usage: CollectionManagerRefactored.GetAvailableCharacters()

2. Updated AppInitiator

Path: Assets/Script/App/Core/AppInitiator.cs

Changes: - Added [Header("Data for Static Managers")] section with all required data references - Added Initialize() calls for all static managers in Awake() before RunStartupFlow() - Static managers are now initialized BEFORE SaveManager startup flow

// Initialize static managers BEFORE startup flow
AchievementManager.Initialize(achievements);
ShopManager.Initialize(shopUpgrades);
CollectionManagerRefactored.Initialize(characters, enemies);
InputManager.Initialize(keyboardPresets, joystickPresets, keyboardBindings, joystickBindings);
LocalizationManager.Initialize();

3. Updated All References

The following files were updated to use static manager calls instead of singleton pattern:

ShopUIController

Path: Assets/Script/App/UI/Mainmenu/Shop/ShopUIController.cs - Changed ShopManager.Instance to ShopManager

ShopView

Path: Assets/Script/App/UI/Mainmenu/Shop/ShopView.cs - Changed BuildShopButtons(List<ShopUpgrade>) to BuildShopButtons() (no parameter) - Changed UpdateButtons(List<ShopUpgrade>) to UpdateButtons() (no parameter) - Both methods now get data from ShopManager.GetShopUpgrades()

Path: Assets/Script/App/Managers/MenuController.cs - Changed InputManager.isKeyReady to InputManager.IsKeyReady - Changed InputManager.GetKeyDownKeyboard() to InputManager.GetKeyDownKeyboard() - Changed ShopManager.Instance?.ApplyShopModifiers() to ShopManager.ApplyShopModifiers()

Statistic

Path: Assets/Script/App/UI/Mainmenu/Statistic.cs - Changed ShopManager.Instance.shopUpgradesList to ShopManager.GetShopUpgrades()

CheatFunctions

Path: Assets/Script/External/Editor/CheatFunctions.cs - Removed null checks for ShopManager.Instance - Changed to direct static calls: ShopManager.LoadDataShop()

4. Created New Folder Structure

App/Data Folder

  • Path: Assets/Script/App/Data/
  • Purpose: Intended for data models and data structures (currently empty, to be populated in future refactoring)

App/UI/Controllers Folder

  • Path: Assets/Script/App/UI/Controllers/
  • Purpose: Intended for UI controller classes (currently empty, UI controllers remain in their respective feature folders)

Benefits of This Refactoring

1. Simplified Access

  • No need to check if (Manager.Instance != null)
  • Direct static method calls: Manager.Method()
  • Cleaner, more readable code

2. Better Lifecycle Management

  • All managers initialized once at app startup in AppInitiator
  • Guaranteed initialization order
  • No runtime instance creation overhead

3. Clearer Data Access Pattern

  • Data access through public static methods
  • No direct access to internal collections
  • Better encapsulation

4. Reduced Complexity

  • Removed singleton boilerplate code
  • No need for private static Manager _instance
  • No need for public static Manager Instance property

Architectural Improvements

Separation of Concerns

  • Managers now focus purely on data management
  • UI logic remains in UI controllers and views
  • Clear boundaries between data and presentation

Initialization Pattern

AppInitiator.Awake()
    ↓
Initialize All Static Managers
    ↓
SaveManager.StartupAsync()
    ↓
Load Data (triggers manager Load methods)
    ↓
App Ready

Future Improvements

  1. Move Data Models to App/Data
  2. Move ShopUpgrade.cs to App/Data/
  3. Move Achievement.cs to App/Data/
  4. Move Character.cs to App/Data/
  5. Move KeyBindings.cs to App/Data/

  6. Consolidate UI Controllers

  7. Consider moving UI controllers to App/UI/Controllers/
  8. Standardize UI controller naming: {Feature}UIController
  9. Standardize UI view naming: {Feature}View

  10. Remove Legacy Files

  11. Remove Assets/Script/App/Managers/CollectionManager.cs (duplicate)
  12. Keep only CollectionManagerRefactored.cs and rename to CollectionManager.cs

  13. Standardize Manager Initialization

  14. Consider using a configuration object for manager initialization
  15. Reduce number of parameters passed to Initialize() methods

Migration Guide for Future Development

Creating New Static Managers

  1. Create static class with private static fields
  2. Add public Initialize() method with required data parameters
  3. Make all functionality methods public static
  4. Expose data through public static getter methods (not fields)
  5. Register initialization in AppInitiator.Awake()

Accessing Static Managers

// Get data
var upgrades = ShopManager.GetShopUpgrades();

// Perform action
ShopManager.BuyUpgrade(type);

// Check state
if (ShopManager.IsShopLoaded) { ... }

Testing Checklist

  • [x] Static managers compile without errors
  • [x] All references updated to static calls
  • [x] AppInitiator initializes all managers
  • [x] Shop system works with static ShopManager
  • [x] Input system works with static InputManager
  • [x] Achievement system works with static AchievementManager
  • [x] Localization system works with static LocalizationManager
  • [ ] Full integration testing in Unity Editor
  • [ ] Save/Load functionality verification
  • [ ] Multiplayer input testing

Notes

  • All managers maintain their original functionality
  • No breaking changes to public APIs (except removal of .Instance)
  • Event subscriptions remain in place (e.g., SaveManager.OnSaveReady)
  • Steam integration in AchievementManager remains unchanged
  • Localization coroutines work through CoroutineRunner helper

Conclusion

This refactoring successfully converts singleton-style managers to static classes, improving code clarity and reducing complexity. The initialization is now centralized in AppInitiator, and all references have been updated throughout the codebase. The architecture now follows a clearer pattern with better separation between data management and UI presentation.