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
Instanceproperty - Changed all instance methods to static methods
- Made
shopUpgradesListprivate 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
Instanceproperty - Changed all instance methods to static methods
- Made
achievementsandpopupQueueprivate static - Added
Initialize()method for setup - Added
GetPopupQueue()public method for UI access - Added
IsAchievementLoadedpublic static property
Old usage: AchievementManager.UpdateAchievementProgress(id)
New usage: AchievementManager.UpdateAchievementProgress(id)
InputManager¶
- Path:
Assets/Script/App/Managers/InputManager.cs - Changes:
- Removed
Instanceproperty - Changed all instance methods to static methods
- Made all data fields private static
- Added
Initialize()method for setup with multiple parameters - Made
IsKeyReadypublic static property
Old usage: InputManager.GetKeyDownKeyboard("Back", 0)
New usage: InputManager.GetKeyDownKeyboard("Back", 0)
LocalizationManager¶
- Path:
Assets/Script/App/Managers/LocalizationManager.cs - Changes:
- Removed
Instanceproperty - Changed all instance methods to static methods
- Made
buttonsprivate static - Added
Initialize()method for setup - Created
CoroutineRunnersingleton 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
Instanceproperty - Changed all instance methods to static methods
- Made
charactersandenemiesprivate 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()
MenuController¶
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 Instanceproperty
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¶
Recommended Next Steps¶
- Move Data Models to App/Data
- Move ShopUpgrade.cs to App/Data/
- Move Achievement.cs to App/Data/
- Move Character.cs to App/Data/
-
Move KeyBindings.cs to App/Data/
-
Consolidate UI Controllers
- Consider moving UI controllers to App/UI/Controllers/
- Standardize UI controller naming:
{Feature}UIController -
Standardize UI view naming:
{Feature}View -
Remove Legacy Files
- Remove
Assets/Script/App/Managers/CollectionManager.cs(duplicate) -
Keep only
CollectionManagerRefactored.csand rename toCollectionManager.cs -
Standardize Manager Initialization
- Consider using a configuration object for manager initialization
- Reduce number of parameters passed to
Initialize()methods
Migration Guide for Future Development¶
Creating New Static Managers¶
- Create static class with private static fields
- Add public
Initialize()method with required data parameters - Make all functionality methods public static
- Expose data through public static getter methods (not fields)
- 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.