Skip to content

GameInitializer (ImprovedGameInitializer)

Note: The legacy GameInitializer class was removed in v0.14.0. Use ImprovedGameInitializer in 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

  1. In Project window: Right-click > Create > LoLEngine > Service Configuration
  2. Name it DefaultServiceConfiguration
  3. 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

  1. In Project window: Right-click > Create > LoLEngine > Resource Path Config
  2. Name it DefaultResourcePathConfig
  3. 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

  1. Create an empty GameObject in your first scene (e.g., "Boot" scene)
  2. Name it "EngineInitializer" or "GameInitializer"
  3. Add the ImprovedGameInitializer component
  4. 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"
    }
}

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:

  1. Singleton Setup (HandleSingletonPattern)
  2. Ensures only one instance exists
  3. Registers with EngineInitializationRegistry
  4. Sets up DontDestroyOnLoad if enabled

  5. Logging Setup (SetupLogging)

  6. Configures log level
  7. Enables detailed logging if requested

  8. Configuration Validation (ValidateConfiguration)

  9. Validates ServiceConfiguration
  10. Validates ResourcePathConfig
  11. Creates defaults if missing

  12. Service Initializer Creation (CreateServiceInitializer)

  13. Creates ConfigurableServiceInitializer
  14. Passes configurations

  15. Service Initialization (InitializeServicesAsync)

  16. Initializes services based on configuration
  17. Supports async initialization
  18. Handles dependencies between services

  19. Completion (OnEngineInitialized)

  20. Marks initialization as complete
  21. Calls virtual method for custom initialization
  22. 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

  1. Remove old GameInitializer component
  2. Add ImprovedGameInitializer component
  3. 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.