GameInitializer (ImprovedGameInitializer)¶
Note: The legacy
GameInitializerclass was removed in v0.14.0. UseImprovedGameInitializerin all new projects.
ImprovedGameInitializer is the recommended entry point for the LoL Engine. It provides a modern, configuration-based approach with async support, better lifecycle management, and improved extensibility.
Overview¶
ImprovedGameInitializer replaces the hardcoded service initialization approach with a flexible, configuration-driven system that supports:
- Configuration-Based Service Loading: Define which services to load via ScriptableObjects
- Async Initialization: Full async/await support for services that need it (e.g., Addressables)
- Better Lifecycle Management: Proper singleton pattern with domain reload support
- ServiceAwaiter Integration: Works seamlessly with the ServiceAwaiter utility
- Resource Path Configuration: Centralized resource path management
- Detailed Logging: Configurable logging for debugging initialization issues
Key Features¶
- Configuration-driven service initialization
- Async/await support for service initialization
- Singleton pattern with proper cleanup
- DontDestroyOnLoad handling with scene awareness
- Version information display
- Validation system for configurations
- ServiceAwaiter integration via
IEngineInitializationProvider - Domain reload safety
- Editor utilities for validation and re-initialization
Setup¶
1. Create Configuration Assets¶
First, create the required configuration ScriptableObjects:
ServiceConfiguration Asset¶
- In Project window:
Right-click > Create > LoLEngine > Service Configuration - Name it
DefaultServiceConfiguration - Configure which services to enable (inspector labels match
ServiceConfiguration):
Core Services:
├── Enable Event Manager: [x]
├── Enable Object Pool: [x]
├── Enable Time Service: [x]
├── Enable Resource Service: [x]
└── Enable Rng Service: [x]
Feature Services:
├── Enable Audio Service: [x]
├── Enable Data Persistence Service: [x]
├── Enable Localization Service: [x]
├── Enable Serialization / Compression / Encryption: [x]
├── Enable Auto Save Service: [x]
└── Enable Notification Service: [x]
Game Services:
└── Enable Game State Manager: [x]
Auto-save interval and slot settings live on SaveConfig (not ServiceConfiguration).
ResourcePathConfig Asset¶
- In Project window:
Right-click > Create > LoLEngine > Resource Path Config - Name it
DefaultResourcePathConfig - Configure base paths (combined at runtime):
Base Paths:
├── Engine Resource Root: "" (or your project prefix)
├── Configs Path: "Configs/"
└── Localization Path: "Localization/"
Default Config Names (resolved under Configs Path):
├── DefaultLoLEngineConfig
├── DefaultAudioConfig
├── DefaultLocalizationConfig
├── DefaultSaveConfig
└── DefaultResourceManagementConfig
2. Scene Setup¶
- Create an empty GameObject in your first scene (e.g., "Boot" scene)
- Name it "EngineInitializer" or "GameInitializer"
- Add the
ImprovedGameInitializercomponent - Configure the inspector:
// Inspector Configuration
[Configuration]
Service Configuration: DefaultServiceConfiguration
Resource Path Configuration: DefaultResourcePathConfig
[Engine Settings]
Don't Destroy On Load: [x]
Initialize In Awake: [x]
[Debugging]
Enable Detailed Logging: [ ]
Log Level: Warning
Basic Usage¶
Accessing the Initializer¶
using LoLEngine.Core.GameInitializer;
public class MyGameManager : MonoBehaviour
{
void Start()
{
// Check if engine is initialized
if (ImprovedGameInitializer.Instance != null &&
ImprovedGameInitializer.Instance.IsInitialized)
{
Debug.Log("LoL Engine is ready!");
}
// Get initialization status
string status = ImprovedGameInitializer.Instance.GetInitializationStatus();
Debug.Log($"Engine Status: {status}"); // "Initialized", "Not Initialized", or "Shutting Down"
}
}
Using ServiceAwaiter (Recommended)¶
The recommended way to wait for services is using the ServiceAwaiter utility:
using LoLEngine.Core.ServiceManagement.Service;
using LoLEngine.Runtime;
public class PlayerController : MonoBehaviour
{
private IAudioService _audioService;
void Start()
{
ServiceAwaiter.WaitForServices(this, OnServicesReady, OnServicesTimeout);
}
private void OnServicesReady()
{
// All services are now initialized and ready to use
_audioService = ServiceLocator.Instance.Get<IAudioService>();
if (_audioService != null)
{
Debug.Log("Audio service is ready!");
// Initialize your game logic here
}
}
private void OnServicesTimeout()
{
Debug.LogError("Services failed to initialize within timeout period");
}
}
Manual Coroutine Wait (Alternative)¶
If you prefer coroutines:
using LoLEngine.Core.GameInitializer;
public class GameManager : MonoBehaviour
{
void Start()
{
StartCoroutine(WaitForInitialization());
}
private IEnumerator WaitForInitialization()
{
// Wait for ImprovedGameInitializer to exist and be initialized
yield return new WaitUntil(() =>
ImprovedGameInitializer.Instance != null &&
ImprovedGameInitializer.Instance.IsInitialized
);
// Now safe to use services
InitializeGameSystems();
}
private void InitializeGameSystems()
{
var audioService = ServiceLocator.Instance.Get<IAudioService>();
// ... initialize your game
}
}
Advanced Usage¶
Extending ImprovedGameInitializer¶
Create a custom initializer for game-specific initialization:
using LoLEngine.Core.GameInitializer;
using UnityEngine;
public class MyGameInitializer : ImprovedGameInitializer
{
[Header("Game-Specific Configuration")]
[SerializeField] private MyGameConfig gameConfig;
[SerializeField] private PlayerDataConfig playerConfig;
protected override void OnEngineInitialized()
{
// Called after engine initialization is complete
base.OnEngineInitialized();
Debug.Log("Engine initialized, setting up game-specific systems...");
// Register game-specific configurations
if (gameConfig != null)
{
ServiceLocator.Instance.Register(gameConfig);
}
if (playerConfig != null)
{
ServiceLocator.Instance.Register(playerConfig);
}
// Initialize game-specific managers
InitializeGameManagers();
Debug.Log("Game initialization complete!");
}
private void InitializeGameManagers()
{
// Initialize your game-specific systems here
// These can safely access engine services now
}
}
Manual Initialization Control¶
If you need to control when initialization happens:
// In Inspector: Uncheck "Initialize In Awake"
public class BootstrapManager : MonoBehaviour
{
[SerializeField] private ImprovedGameInitializer initializer;
void Start()
{
// Perform pre-initialization tasks
PerformPreInitializationSetup();
// Manually trigger initialization
initializer.InitializeEngine();
}
private void PerformPreInitializationSetup()
{
// Setup analytics, cloud services, etc.
}
}
Async Initialization¶
For advanced scenarios requiring async operations:
using System.Threading.Tasks;
using LoLEngine.Core.GameInitializer;
public class AsyncBootstrap : MonoBehaviour
{
[SerializeField] private ImprovedGameInitializer initializer;
async void Start()
{
// Disable auto-initialization in inspector
await PerformAsyncPreload();
// Initialize engine
await initializer.InitializeEngineAsync();
// Engine is now ready
Debug.Log("Engine initialized asynchronously!");
}
private async Task PerformAsyncPreload()
{
// Load configurations from cloud, etc.
await Task.Delay(1000); // Simulate async work
}
}
Configuration Guide¶
ServiceConfiguration Options¶
// Core Services
EnableEventManager: true
EnableObjectPool: true
EnableTimeService: true
EnableResourceService: true
EnableRngService: true
// Feature Services
EnableAudioService: true
EnableDataPersistenceService: true
EnableLocalizationService: true
EnableSerializationService: true
EnableAutoSaveService: true
EnableNotificationService: true
// Game Services
EnableGameStateManager: true
// Auto-save interval: configure on SaveConfig asset, not here
ResourcePathConfig Paths¶
All paths are relative to Resources/ folder:
Configs/DefaultLocalizationConfig.asset
Configs/DefaultSaveConfig.asset
Configs/DefaultLoLEngineConfig.asset
Configs/DefaultAudioConfig.asset
Configs/DefaultResourceManagementConfig.asset
Debugging Options¶
[Debugging]
Enable Detailed Logging: false // Verbose initialization logs
Log Level: Warning // Minimum log level to display
Initialization Flow¶
The initializer follows this sequence:
- Singleton Setup (
HandleSingletonPattern) - Ensures only one instance exists
- Registers with
EngineInitializationRegistry -
Sets up DontDestroyOnLoad if enabled
-
Logging Setup (
SetupLogging) - Configures log level
-
Enables detailed logging if requested
-
Configuration Validation (
ValidateConfiguration) - Validates ServiceConfiguration
- Validates ResourcePathConfig
-
Creates defaults if missing
-
Service Initializer Creation (
CreateServiceInitializer) - Creates
ConfigurableServiceInitializer -
Passes configurations
-
Service Initialization (
InitializeServicesAsync) - Initializes services based on configuration
- Supports async initialization
-
Handles dependencies between services
-
Completion (
OnEngineInitialized) - Marks initialization as complete
- Calls virtual method for custom initialization
- ServiceAwaiter callbacks are triggered
Best Practices¶
1. Configuration Management¶
- Store configurations in
Assets/Resources/Configs/ - Create default configurations for distribution
- Use version control for configuration files
- Document any custom configuration fields
2. Initialization Timing¶
// GOOD: Use ServiceAwaiter
void Start()
{
ServiceAwaiter.WaitForServices(this, OnServicesReady, OnTimeout);
}
// BAD: Assume services are ready immediately
void Start()
{
var service = ServiceLocator.Instance.Get<IAudioService>(); // May be null if services not ready!
}
3. Scene Structure¶
Boot Scene (First Scene)
├── EngineInitializer (ImprovedGameInitializer)
├── EventSystem (UI)
└── BootstrapUI (Loading screen)
Main Menu Scene
├── MenuManager
└── UI Elements
4. DontDestroyOnLoad¶
- Enable for persistent engine systems
- Initializer automatically handles scene transitions
- Prevents duplicate instances across scenes
5. Error Handling¶
protected override void OnEngineInitialized()
{
try
{
base.OnEngineInitialized();
InitializeGameSystems();
}
catch (Exception ex)
{
Debug.LogError($"Game initialization failed: {ex.Message}");
// Handle initialization failure gracefully
}
}
Troubleshooting¶
Services Not Available¶
Problem: ServiceLocator.Instance.Get<T>() returns null
Solutions:
1. Check if engine is initialized: ImprovedGameInitializer.Instance.IsInitialized
2. Use ServiceAwaiter instead of immediate access
3. Verify service is enabled in ServiceConfiguration
4. Check logs for initialization errors
Multiple Initializers¶
Problem: Warning about multiple initializer instances
Solutions: 1. Ensure only one ImprovedGameInitializer exists in first scene 2. Check for duplicate GameObjects across loaded scenes 3. Verify DontDestroyOnLoad is working correctly
Configuration Not Found¶
Problem: Warnings about missing configurations
Solutions:
1. Verify configurations exist in Resources/Configs/
2. Check ResourcePathConfig paths are correct
3. Use "Validate Setup" context menu in inspector
4. Ensure configuration assets are included in build
Initialization Timeout¶
Problem: ServiceAwaiter timeout callback is triggered
Solutions: 1. Check console for initialization errors 2. Increase ServiceAwaiter timeout if needed 3. Verify all required configuration assets exist 4. Check for exceptions during service initialization
Editor Utilities¶
Context Menu Actions¶
Right-click on ImprovedGameInitializer component:
Force Re-initialization
└── Shuts down and re-initializes the engine (useful for testing)
Validate Setup
└── Checks if configurations are properly assigned
Debug Information¶
// Get current initialization status
string status = ImprovedGameInitializer.Instance.GetInitializationStatus();
// Returns: "Initialized", "Not Initialized", or "Shutting Down"
// Check if initialized
bool isReady = ImprovedGameInitializer.Instance.IsInitialized;
// Access version information (logged on initialization)
// Check console for version details of all modules
Migration from Legacy GameInitializer¶
Step 1: Create Configurations¶
Create ServiceConfiguration and ResourcePathConfig assets as described in Setup section.
Step 2: Replace Component¶
- Remove old
GameInitializercomponent - Add
ImprovedGameInitializercomponent - Assign configuration assets
Step 3: Update Code References¶
// OLD
GameInitializer.Instance.IsInitialized
// NEW
ImprovedGameInitializer.Instance.IsInitialized
Step 4: Update Service Access¶
// OLD: Direct access (risky)
var service = ServiceLocator.Instance.Get<IAudioService>();
// NEW: Use ServiceAwaiter (safe)
ServiceAwaiter.WaitForServices(this, OnServicesReady, OnTimeout);
Key Differences¶
| Feature | GameInitializer | ImprovedGameInitializer |
|---|---|---|
| Configuration | Hardcoded | ScriptableObject-based |
| Async Support | No | Yes |
| Lifecycle Management | Basic | Improved with domain reload support |
| ServiceAwaiter | No | Yes via IEngineInitializationProvider |
| Validation | No | Yes Built-in validation |
| Extensibility | Limited | OnEngineInitialized callback |
Example Project Structure¶
Assets/
├── Resources/
│ ├── Configs/
│ │ ├── DefaultServiceConfiguration.asset
│ │ ├── DefaultResourcePathConfig.asset
│ │ ├── DefaultLocalizationConfig.asset
│ │ ├── DefaultSaveConfig.asset
│ │ ├── DefaultLoLEngineConfig.asset
│ │ ├── DefaultAudioConfig.asset
│ │ └── DefaultResourceManagementConfig.asset
├── Scenes/
│ ├── Boot.unity # First scene with ImprovedGameInitializer
│ ├── MainMenu.unity
│ └── Gameplay.unity
└── Scripts/
├── Initialization/
│ └── MyGameInitializer.cs # Custom initializer extending ImprovedGameInitializer
└── Managers/
└── GameManager.cs # Uses ServiceAwaiter
Performance Considerations¶
- Async initialization prevents frame drops during startup
- Configuration-based loading only initializes needed services
- Proper cleanup prevents memory leaks on scene transitions
- ServiceAwaiter prevents repeated polling for service availability
Version Information¶
The initializer automatically logs version information on startup:
=== LoL Engine Version Information ===
LoLEngine: vX.Y.Z
CoreEngine: vX.Y.Z
Unity Version: <your Unity version>
======================================
This helps with debugging and version tracking.