Files
AppleHillsProduction/docs/managed_bejavior.md
2025-11-05 20:37:16 +01:00

51 KiB

ManagedBehaviour Lifecycle System - Implementation Guide

Overview

This document provides a step-by-step implementation plan for creating a custom lifecycle management system that extends MonoBehaviour with deterministic, ordered lifecycle hooks. The system integrates with existing bootstrap, scene management, save/load, and game state management infrastructure.


Current System Analysis

Existing Lifecycle Flow

  1. Unity Bootstrap Phase

    • RuntimeInitializeOnLoadMethod(BeforeSplashScreen)CustomBoot.Initialise()
    • Loads CustomBootSettings via Addressables
    • BootstrapScene loads with initial GameObjects
  2. Unity Standard Lifecycle

    • Awake() - All MonoBehaviours (unordered within frame)
    • OnEnable() - After Awake phase
    • Start() - After OnEnable phase
    • Game loop: Update(), FixedUpdate(), LateUpdate()
  3. Custom Bootstrap Integration

    • Components register with BootCompletionService.RegisterInitAction() in Awake()
    • CustomBoot completes → triggers BootCompletionService.HandleBootCompleted()
    • BootCompletionService executes registered actions (priority-sorted, 0-1000+)
    • Components implement InitializePostBoot() methods
  4. Scene Lifecycle Integration

    • SceneManagerService manages additive scene loading/unloading
    • Components subscribe to SceneLoadCompleted and SceneUnloadStarted events
    • SceneManagerService.SwitchSceneAsync() handles scene transitions
  5. Save/Load System

    • SaveLoadManager maintains registry of ISaveParticipant components
    • Components call RegisterParticipant() in post-boot initialization
    • Components call UnregisterParticipant() in OnDestroy()
    • State restoration happens after load or when new participants register
  6. Game State Management (GameManager)

    • Pause/Resume system with counter-based requests
    • IPausable component registration (manual Subscribe/Unsubscribe)
    • Settings initialization (ServiceLocator pattern)
    • Developer settings integration

Existing Patterns

  • Singleton Pattern: All managers use _instance field with Instance property
  • Two-Phase Init: Awake() + InitializePostBoot()
  • Priority-Based Boot: Components specify boot priority (10-100+, lower = earlier)
  • Manual Event Management: Subscribe in OnEnable/Start, unsubscribe in OnDestroy
  • Inheritance Example: InteractionActionBase provides protected virtual lifecycle hooks

Architecture Design

Core Components

1. LifecycleManager (Singleton)

Central orchestrator that:

  • Maintains registries of all ManagedBehaviours (separate lists per lifecycle phase)
  • Broadcasts lifecycle events in priority-sorted order
  • Integrates with BootCompletionService, SceneManagerService, SaveLoadManager, GameManager
  • Handles late registration and edge cases
  • Provides optional debug/profiling tools

2. ManagedBehaviour (Base Class)

Enhanced MonoBehaviour providing:

  • Virtual lifecycle hooks (opt-in via override)
  • Automatic registration/unregistration with LifecycleManager
  • Priority/ordering support via properties
  • Built-in managed event subscription system (auto-cleanup)
  • Optional auto-integration with SaveLoadManager and GameManager

3. ManagedEvent System

Helper system for automatic event subscription cleanup:

  • Stores event subscriptions internally
  • Auto-unsubscribes all events on destruction
  • Prevents memory leaks and manual cleanup

Lifecycle Phases

Complete Lifecycle Flow

┌─────────────────────────────────────────────────────────────┐
│ PHASE 1: UNITY ENGINE BOOTSTRAP                             │
│ - RuntimeInitializeOnLoadMethod (CustomBoot.Initialise)    │
│ - BootstrapScene loads                                      │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ PHASE 2: UNITY STANDARD LIFECYCLE                           │
│ - Unity Awake() [all MonoBehaviours]                        │
│   └→ ManagedBehaviour.Awake() auto-registers with Manager  │
│ - Unity OnEnable()                                          │
│ - Unity Start()                                             │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ PHASE 3: MANAGED AWAKE (Deterministic)                      │
│ - LifecycleManager.BroadcastManagedAwake()                 │
│ - Calls OnManagedAwake() in priority order (0→1000)        │
│ - Singleton initialization, component setup                │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ PHASE 4: BOOT COMPLETION                                    │
│ - CustomBoot completes                                      │
│ - BootCompletionService.HandleBootCompleted()              │
│ - LifecycleManager.BroadcastBootComplete()                 │
│ - Calls OnBootComplete() in priority order                  │
│ - Settings loaded, services initialized                    │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ PHASE 5: SCENE READY                                        │
│ - SceneManagerService finishes loading                     │
│ - LifecycleManager.BroadcastSceneReady()                   │
│ - Calls OnSceneReady() for all active ManagedBehaviours    │
│ - Scene-specific initialization                            │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ PHASE 6: GAME LOOP (Runtime)                               │
│ - Unity Update/FixedUpdate/LateUpdate                      │
│ - Optional: OnManagedUpdate() (priority-ordered)           │
│ - Optional: OnManagedFixedUpdate() (priority-ordered)      │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ PHASE 7: PAUSE/RESUME (State Change)                       │
│ - GameManager.RequestPause() / ReleasePause()              │
│ - LifecycleManager.BroadcastPause/Resume()                 │
│ - Calls OnPaused() / OnResumed() for all active            │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ PHASE 8: SCENE UNLOADING (Transition)                      │
│ - SceneManagerService.SwitchSceneAsync() starts            │
│ - LifecycleManager.BroadcastSceneUnloading()              │
│ - Calls OnSceneUnloading() for scene-specific components   │
│ - Cleanup before scene unload                              │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ PHASE 9: DESTRUCTION                                        │
│ - Unity OnDisable()                                         │
│ - Unity OnDestroy()                                         │
│   └→ ManagedBehaviour.OnDestroy() auto-unregisters        │
│ - LifecycleManager.BroadcastManagedDestroy()              │
│ - Calls OnManagedDestroy() in reverse priority order       │
│ - Auto-cleanup of managed events                           │
└─────────────────────────────────────────────────────────────┘

Lifecycle Hook Reference

Hook Name Priority Order When Called Use Case
OnManagedAwake() Low→High (0→∞) After Unity Awake, before Start Deterministic initialization
OnBootComplete() Low→High (0→∞) After CustomBoot completes Post-boot initialization (replaces InitializePostBoot)
OnSceneReady() Low→High (0→∞) After scene fully loaded Scene-specific setup
OnManagedUpdate() Low→High (0→∞) Every frame (optional) Ordered per-frame logic
OnManagedFixedUpdate() Low→High (0→∞) Every physics frame (optional) Ordered physics logic
OnPaused() Low→High (0→∞) When game pauses Pause state handling
OnResumed() Low→High (0→∞) When game resumes Resume state handling
OnSceneUnloading() High→Low (∞→0) Before scene unloads Scene cleanup
OnManagedDestroy() High→Low (∞→0) Before Unity OnDestroy Guaranteed cleanup

Implementation Steps

STEP 1: Create Core Enums and Interfaces

File: Assets/Scripts/Core/Lifecycle/LifecycleEnums.cs

Actions:

  1. Create namespace Core.Lifecycle
  2. Define LifecyclePhase enum with all phases
  3. Define LifecycleFlags enum for component opt-in (bitflags)
  4. Add XML documentation for each value

Key Details:

  • LifecyclePhase: ManagedAwake, BootComplete, SceneReady, Update, FixedUpdate, Paused, Resumed, SceneUnloading, ManagedDestroy
  • LifecycleFlags: None, ManagedAwake, BootComplete, SceneReady, ManagedUpdate, ManagedFixedUpdate, Pause, SceneUnloading, ManagedDestroy, All (bitwise OR of all)

STEP 2: Create ManagedEvent System

File: Assets/Scripts/Core/Lifecycle/ManagedEventSubscription.cs

Actions:

  1. Create internal struct ManagedEventSubscription to store event delegate and target
  2. Create class ManagedEventManager with:
    • List of subscriptions per ManagedBehaviour
    • RegisterEvent<T>(target, action) method
    • UnregisterAllEvents() method that invokes -= on all stored subscriptions
  3. Handle both Action and generic Action<T> delegates
  4. Use reflection to dynamically unsubscribe

Key Details:

  • Store event info as: object target (event owner), Delegate handler, string eventName
  • Support common Unity event patterns (Action, Action<T>, UnityEvent, etc.)
  • Provide safe null checks before unsubscribing

STEP 3: Create ManagedBehaviour Base Class (Structure)

File: Assets/Scripts/Core/Lifecycle/ManagedBehaviour.cs

Actions:

  1. Create abstract class ManagedBehaviour : MonoBehaviour
  2. Add virtual properties for priorities:
    • ManagedAwakePriority (default 100)
    • BootCompletePriority (default 100)
    • SceneReadyPriority (default 100)
    • UpdatePriority (default 100)
    • DestroyPriority (default 100)
  3. Add property ActiveLifecyclePhases (returns LifecycleFlags, default None)
  4. Add property AutoRegisterSaveParticipant (default false)
  5. Add property AutoRegisterPausable (default false)
  6. Add property IsPersistent (default false) - survives scene changes
  7. Add private field ManagedEventManager _eventManager
  8. Add private bool _isRegistered to track registration state

Key Details:

  • All priority properties are virtual so subclasses can override
  • ActiveLifecyclePhases determines which hooks are called (opt-in)
  • IsPersistent flag controls whether component persists across scenes

STEP 4: Implement ManagedBehaviour Lifecycle Hooks (Virtual Methods)

File: Assets/Scripts/Core/Lifecycle/ManagedBehaviour.cs (continued)

Actions:

  1. Add virtual protected methods (empty by default):
    • OnManagedAwake()
    • OnBootComplete()
    • OnSceneReady()
    • OnManagedUpdate()
    • OnManagedFixedUpdate()
    • OnPaused()
    • OnResumed()
    • OnSceneUnloading()
    • OnManagedDestroy()
  2. Add XML documentation for each method
  3. Add protected helper methods:
    • RegisterManagedEvent<T>(target, action) - wraps _eventManager
    • IsLifecyclePhaseActive(LifecyclePhase) - checks flags

Key Details:

  • All hooks are protected virtual void (no return value)
  • Empty implementations allow opt-in override pattern
  • Use [Conditional("UNITY_EDITOR")] attribute for debug-only hooks if needed

STEP 5: Implement ManagedBehaviour Unity Integration

File: Assets/Scripts/Core/Lifecycle/ManagedBehaviour.cs (continued)

Actions:

  1. Implement protected virtual void Awake():
    • Initialize _eventManager
    • Register with LifecycleManager (call LifecycleManager.Instance.Register(this))
    • Set _isRegistered = true
  2. Implement protected virtual void OnDestroy():
    • Unregister from LifecycleManager (call LifecycleManager.Instance.Unregister(this))
    • Call _eventManager.UnregisterAllEvents()
    • Auto-unregister from SaveLoadManager and GameManager if applicable
    • Set _isRegistered = false
  3. Make both methods call base implementation warning (for subclasses)

Key Details:

  • Use null checks for LifecycleManager.Instance (may not exist during shutdown)
  • Provide clear error logging if registration fails
  • Support scenario where subclass overrides Awake/OnDestroy (must call base)

STEP 6: Create LifecycleManager (Structure)

File: Assets/Scripts/Core/Lifecycle/LifecycleManager.cs

Actions:

  1. Create class LifecycleManager : MonoBehaviour
  2. Implement singleton pattern (private static _instance, public static Instance)
  3. Add separate List<ManagedBehaviour> for each lifecycle phase:
    • _managedAwakeList
    • _bootCompleteList
    • _sceneReadyList
    • _updateList
    • _fixedUpdateList
    • _pauseList
    • _sceneUnloadingList
    • _destroyList
  4. Add Dictionary<ManagedBehaviour, int> for tracking which lists each component is in (bitmask)
  5. Add bool flags: _isBootComplete, _isSceneReady, _isPaused
  6. Add queue for late registrations: Queue<ManagedBehaviour> _pendingRegistrations

Key Details:

  • Each list must be kept sorted by priority
  • Use SortedList or List with manual sorting after registration
  • Dictionary tracks which phases each component participates in

STEP 7: Implement LifecycleManager Registration System

File: Assets/Scripts/Core/Lifecycle/LifecycleManager.cs (continued)

Actions:

  1. Implement public void Register(ManagedBehaviour component):
    • Check component.ActiveLifecyclePhases flags
    • Add to appropriate lists based on flags
    • Insert in priority-sorted position
    • Handle auto-registration with SaveLoadManager if component is ISaveParticipant && AutoRegisterSaveParticipant
    • Handle auto-registration with GameManager if component is IPausable && AutoRegisterPausable
    • If boot already complete and component has BootComplete flag, immediately call OnBootComplete
    • If scene already ready and component has SceneReady flag, immediately call OnSceneReady
  2. Implement public void Unregister(ManagedBehaviour component):
    • Remove from all lists
    • Handle auto-unregistration from SaveLoadManager and GameManager

Key Details:

  • Use binary search for insertion point (lists sorted by priority)
  • Handle edge case: registration during broadcast (queue and process later)
  • Validate component is not null and has valid priorities

STEP 8: Implement LifecycleManager Broadcast System

File: Assets/Scripts/Core/Lifecycle/LifecycleManager.cs (continued)

Actions:

  1. Implement broadcast methods for each phase:
    • BroadcastManagedAwake()
    • BroadcastBootComplete()
    • BroadcastSceneReady()
    • BroadcastPause()
    • BroadcastResume()
    • BroadcastSceneUnloading()
    • BroadcastManagedDestroy()
  2. Each method iterates through corresponding list and calls hook
  3. Add try-catch around each call with error logging
  4. Process pending registrations after broadcast completes
  5. Set state flags (_isBootComplete, _isSceneReady, _isPaused)

Key Details:

  • Iterate forward for normal phases (low→high priority)
  • Iterate backward for cleanup phases (SceneUnloading, ManagedDestroy)
  • Use for loop with index (not foreach) to handle list modifications
  • Log phase start/end with timing info (use Stopwatch)

STEP 9: Implement LifecycleManager Update Handlers

File: Assets/Scripts/Core/Lifecycle/LifecycleManager.cs (continued)

Actions:

  1. Implement void Update():
    • Check if _updateList is empty (skip if so)
    • Iterate _updateList and call OnManagedUpdate() on each
    • Add try-catch with error logging
  2. Implement void FixedUpdate():
    • Check if _fixedUpdateList is empty (skip if so)
    • Iterate _fixedUpdateList and call OnManagedFixedUpdate() on each
    • Add try-catch with error logging
  3. Add optimization: disable Update/FixedUpdate when lists are empty

Key Details:

  • Use enabled = false when no components registered for updates
  • Re-enable when first component registers
  • Consider pooling/caching for performance

STEP 10: Integrate LifecycleManager with Bootstrap

File: Assets/Scripts/Core/Lifecycle/LifecycleManager.cs (continued)

Actions:

  1. In Awake():
    • Set singleton instance
    • Subscribe to BootCompletionService.OnBootComplete
    • Set up initial state
  2. Implement handler for BootCompletionService.OnBootComplete:
    • Set _isBootComplete = true
    • Call BroadcastManagedAwake() first (if not already called)
    • Then call BroadcastBootComplete()
  3. Add Start() method:
    • Call BroadcastManagedAwake() if boot not complete yet (fallback)

Key Details:

  • LifecycleManager should exist in BootstrapScene (persistent)
  • Must handle both editor and runtime initialization
  • Consider RuntimeInitializeOnLoadMethod for creation if needed

STEP 11: Integrate LifecycleManager with SceneManagerService

File: Assets/Scripts/Core/Lifecycle/LifecycleManager.cs (continued)

Actions:

  1. In post-boot initialization:
    • Subscribe to SceneManagerService.Instance.SceneLoadCompleted
    • Subscribe to SceneManagerService.Instance.SceneUnloadStarted
  2. Implement handler for SceneLoadCompleted:
    • Set _isSceneReady = true
    • Call BroadcastSceneReady()
    • Handle scene-specific vs persistent components (check IsPersistent flag)
  3. Implement handler for SceneUnloadStarted:
    • Set _isSceneReady = false
    • Call BroadcastSceneUnloading()
    • Only call on scene-specific components (IsPersistent = false)
  4. In OnDestroy():
    • Unsubscribe from all events

Key Details:

  • Track which scene each component belongs to (use component.gameObject.scene)
  • Only broadcast SceneReady/Unloading to components in affected scene
  • Persistent components (BootstrapScene) should not receive scene lifecycle events

STEP 12: Integrate LifecycleManager with GameManager (Pause System)

File: Assets/Scripts/Core/Lifecycle/LifecycleManager.cs (continued)

Actions:

  1. In post-boot initialization:
    • Subscribe to GameManager.Instance.OnGamePaused
    • Subscribe to GameManager.Instance.OnGameResumed
  2. Implement handler for OnGamePaused:
    • Set _isPaused = true
    • Call BroadcastPause()
  3. Implement handler for OnGameResumed:
    • Set _isPaused = false
    • Call BroadcastResume()

Key Details:

  • Components can opt-in to pause events via ActiveLifecyclePhases flags
  • BroadcastPause/Resume iterates _pauseList only
  • Late-registered components get immediate pause state if game is paused

STEP 13: Add Debug and Profiling Tools

File: Assets/Scripts/Core/Lifecycle/LifecycleManager.cs (continued)

Actions:

  1. Add [SerializeField] private bool enableDebugLogging = false
  2. Add [SerializeField] private bool enableProfilingMarkers = true
  3. Create LogDebugMessage() helper that checks flag
  4. Add Unity Profiler markers around each broadcast phase
  5. Implement GetRegisteredComponents() method for inspector/debugging
  6. Add OnGUI() debug overlay showing:
    • Registered component counts per phase
    • Current lifecycle state flags
    • Last broadcast timings

Key Details:

  • Use UnityEngine.Profiling.ProfilerMarker for zero-cost profiling in builds
  • Debug overlay only active in editor or development builds
  • Consider creating custom inspector for LifecycleManager

STEP 14: Create LifecycleManager Prefab

File: Assets/Prefabs/Core/LifecycleManager.prefab

Actions:

  1. Create empty GameObject named "LifecycleManager"
  2. Add LifecycleManager component
  3. Configure default settings (debug logging off, profiling on)
  4. Save as prefab
  5. Add to BootstrapScene if not already present
  6. Verify it persists across scenes (should be in BootstrapScene which is additive)

Key Details:

  • Only one instance should exist (singleton)
  • Should be in BootstrapScene, not in gameplay scenes
  • Consider adding validation script to prevent duplicates

STEP 15: Update Bootstrap Integration

File: Assets/Scripts/Bootstrap/BootCompletionService.cs

Actions:

  1. In HandleBootCompleted() method, add:
    • Before executing initialization actions, notify LifecycleManager
    • Call LifecycleManager.Instance?.OnBootCompletionStarting() (new method)
  2. After initialization actions complete:
    • Call existing OnBootComplete?.Invoke()
    • LifecycleManager handles this via event subscription

File: Assets/Scripts/Bootstrap/CustomBoot.cs

Actions:

  1. Verify LifecycleManager exists before CustomBoot completes
  2. Add fallback: if LifecycleManager doesn't exist, log warning

Key Details:

  • BootCompletionService remains authoritative for boot completion
  • LifecycleManager observes and broadcasts to ManagedBehaviours
  • Maintain backward compatibility with existing RegisterInitAction pattern

STEP 16: Extend SaveLoadManager Integration

File: Assets/Scripts/Core/SaveLoad/SaveLoadManager.cs

Actions:

  1. Add public method AutoRegisterParticipant(ISaveParticipant participant, ManagedBehaviour owner):
    • Same as RegisterParticipant but stores reference to owner ManagedBehaviour
    • Allows automatic unregistration when owner is destroyed
  2. Add public method AutoUnregisterParticipant(ManagedBehaviour owner):
    • Looks up participant by owner reference and unregisters
  3. Store Dictionary<ManagedBehaviour, string> to track auto-registrations

File: Assets/Scripts/Core/Lifecycle/ManagedBehaviour.cs

Actions:

  1. In Awake() registration:
    • Check if this is ISaveParticipant and AutoRegisterSaveParticipant == true
    • If yes, call SaveLoadManager.Instance.AutoRegisterParticipant(this as ISaveParticipant, this)
  2. In OnDestroy() cleanup:
    • Call SaveLoadManager.Instance.AutoUnregisterParticipant(this)

Key Details:

  • Only auto-register after boot completes (SaveLoadManager must be initialized)
  • Handle null checks (SaveLoadManager may not exist in editor)
  • Log when auto-registration occurs (debug mode)

STEP 17: Extend GameManager Pausable Integration

File: Assets/Scripts/Core/GameManager.cs

Actions:

  1. Add public method AutoRegisterPausable(IPausable component, ManagedBehaviour owner):
    • Same as RegisterPausableComponent but stores owner reference
  2. Add public method AutoUnregisterPausable(ManagedBehaviour owner):
    • Looks up pausable by owner and unregisters
  3. Store Dictionary<ManagedBehaviour, IPausable> to track auto-registrations

File: Assets/Scripts/Core/Lifecycle/ManagedBehaviour.cs

Actions:

  1. In post-boot registration (called by LifecycleManager):
    • Check if this is IPausable and AutoRegisterPausable == true
    • If yes, call GameManager.Instance.AutoRegisterPausable(this as IPausable, this)
  2. In OnDestroy() cleanup:
    • Call GameManager.Instance.AutoUnregisterPausable(this)

Key Details:

  • Wait until boot completes before registering with GameManager
  • Handle case where component implements both ISaveParticipant and IPausable
  • Verify GameManager exists before calling

STEP 18: Create Migration Helper Attribute

File: Assets/Scripts/Core/Lifecycle/RequiresManagedBehaviourAttribute.cs

Actions:

  1. Create custom attribute [RequiresManagedBehaviour]
  2. Can be applied to classes that should be converted to ManagedBehaviour
  3. Create custom inspector that shows warning if class derives from MonoBehaviour instead

File: Assets/Editor/ManagedBehaviourValidation.cs

Actions:

  1. Create editor script that scans project for components with attribute
  2. Shows list of components needing migration
  3. Provides "Convert to ManagedBehaviour" button for each
  4. Automatic string replacement in source files

Key Details:

  • Editor-only functionality (Assets/Editor folder)
  • Use AssetDatabase to find and modify scripts
  • Show before/after preview before conversion

STEP 19: Create Example ManagedBehaviour Implementations

File: Assets/Scripts/Core/Lifecycle/Examples/ExampleManagedSingleton.cs

Actions:

  1. Create example showing singleton pattern with ManagedBehaviour
  2. Demonstrate priority usage
  3. Show lifecycle hook overrides
  4. Include code comments explaining each part

File: Assets/Scripts/Core/Lifecycle/Examples/ExampleManagedComponent.cs

Actions:

  1. Create example showing scene-specific component
  2. Demonstrate managed event subscription
  3. Show auto-save participant integration
  4. Show auto-pausable integration

File: Assets/Scripts/Core/Lifecycle/Examples/ExampleManagedManager.cs

Actions:

  1. Create example showing persistent manager
  2. Demonstrate all lifecycle phases
  3. Show priority ordering
  4. Include performance considerations

Key Details:

  • Well-commented code for reference
  • Cover common use cases (singleton, scene component, manager)
  • Include unit tests if applicable

STEP 20: Migrate Core Systems (Phase 1)

Priority Order: GameManager → SceneManagerService → SaveLoadManager → InputManager

File: Assets/Scripts/Core/GameManager.cs

Actions:

  1. Change class declaration: public class GameManager : ManagedBehaviour
  2. Override properties:
    • protected override int ManagedAwakePriority => 10; (very early)
    • protected override int BootCompletePriority => 10;
  3. Remove BootCompletionService.RegisterInitAction(InitializePostBoot) from Awake
  4. Rename InitializePostBoot() to protected override void OnBootComplete()
  5. Move Awake logic to protected override void OnManagedAwake()
  6. Add protected override LifecycleFlags ActiveLifecyclePhases => LifecycleFlags.ManagedAwake | LifecycleFlags.BootComplete;
  7. Keep existing pause/resume system (don't double-integrate)
  8. Remove manual singleton setup (handled by base class)
  9. Test thoroughly

Key Details:

  • GameManager initializes early (priority 10)
  • Keep existing functionality intact
  • Verify settings loading still works
  • Ensure pause system integration works

STEP 21: Migrate Core Systems (Phase 2)

Target: SceneManagerService, SaveLoadManager, InputManager, ItemManager

For Each File:

  1. Change base class to ManagedBehaviour
  2. Set appropriate priorities (15-30 range)
  3. Move InitializePostBoot → OnBootComplete
  4. Remove manual BootCompletionService registration
  5. Add ActiveLifecyclePhases flags
  6. Test scene transitions, save/load, input handling

Priorities:

  • SceneManagerService: 15 (after GameManager)
  • SaveLoadManager: 20 (after SceneManagerService)
  • InputManager: 25 (after SaveLoadManager)
  • ItemManager: 30 (general manager)

Key Details:

  • Verify event subscriptions still work
  • Check scene loading/unloading
  • Validate save/load system
  • Test input handling in different modes

STEP 22: Migrate UI Systems

Target: UIPageController, LoadingScreenController, PauseMenu, CardSystemUI components

For Each File:

  1. Change base class to ManagedBehaviour
  2. Set priority 50-100 (standard range)
  3. Convert InitializePostBoot → OnBootComplete
  4. Use RegisterManagedEvent for event subscriptions
  5. Add OnSceneReady override if needed for scene-specific UI
  6. Test UI navigation, loading screens, pause menu

Key Details:

  • UI generally has lower priority than managers
  • Scene-specific UI should override OnSceneReady
  • Use AutoRegisterSaveParticipant for UI with state

STEP 23: Migrate Gameplay Systems

Target: PuzzleManager, DivingGameManager, CinematicsManager, CardSystemManager

For Each File:

  1. Change base class to ManagedBehaviour
  2. Set priority 100-200 (gameplay systems)
  3. Convert InitializePostBoot → OnBootComplete
  4. Use OnSceneReady for scene-specific setup
  5. Use OnSceneUnloading for cleanup
  6. Consider AutoRegisterSaveParticipant
  7. Test gameplay features

Key Details:

  • Scene-specific managers should handle OnSceneReady/Unloading
  • Persistent managers (like CardSystemManager) set IsPersistent = true
  • Verify minigame transitions work correctly

STEP 24: Migrate Interaction Systems

Target: Interactable, InteractionActionBase, DialogueComponent

File: Assets/Scripts/Interactions/InteractionActionBase.cs

Actions:

  1. Change base class from MonoBehaviour to ManagedBehaviour
  2. Change protected virtual void Awake() to protected override void OnManagedAwake()
  3. Keep OnEnable/OnDisable as-is (Unity lifecycle needed for enable/disable)
  4. Consider using RegisterManagedEvent for parentInteractable events

Key Details:

  • InteractionActionBase is itself a base class (virtual methods remain)
  • Subclasses inherit ManagedBehaviour capabilities
  • Test interaction flow thoroughly

STEP 25: Migrate Player and Movement Systems

Target: PlayerTouchController, FollowerController

For Each File:

  1. Change base class to ManagedBehaviour
  2. Keep Update() as Unity Update (movement needs every frame)
  3. Use OnBootComplete for post-boot initialization
  4. Use RegisterManagedEvent for InputManager event subscriptions
  5. Test movement, pathfinding, interactions

Key Details:

  • Performance-critical components should use Unity Update, not OnManagedUpdate
  • Only use ManagedBehaviour for initialization/cleanup benefits
  • Verify A* pathfinding still works

STEP 26: Update InteractionActionBase Pattern

File: Assets/Scripts/Interactions/InteractionActionBase.cs

Actions:

  1. Since this is a base class, ensure subclasses can override lifecycle hooks
  2. Add example subclass showing proper override chain
  3. Document pattern for action components

Pattern:

public class MyAction : InteractionActionBase
{
    protected override void OnManagedAwake()
    {
        base.OnManagedAwake(); // Calls parent registration
        // Custom initialization
    }
}

Key Details:

  • Base.OnManagedAwake() must be called in subclasses
  • Provide clear documentation for this pattern
  • Consider sealed methods if override not intended

STEP 27: Create Validation and Testing Suite

File: Assets/Editor/Tests/LifecycleSystemTests.cs

Actions:

  1. Create Unity Test Runner tests for:
    • Registration/unregistration
    • Priority ordering
    • Lifecycle hook execution order
    • Event subscription cleanup
    • Save/load integration
    • Pause system integration
    • Scene transition handling
  2. Create test ManagedBehaviour subclasses
  3. Mock managers for isolated testing

File: Assets/Scripts/Core/Lifecycle/LifecycleValidator.cs

Actions:

  1. Create runtime validator that checks:
    • No duplicate registrations
    • All ManagedBehaviours properly registered
    • Priority conflicts (warnings)
    • Missing overrides (if flags set but no override)
  2. Add menu item "Tools/Lifecycle/Validate Scene"

Key Details:

  • Tests should cover all lifecycle phases
  • Include edge cases (late registration, scene transitions)
  • Performance benchmarks for Update broadcasts

STEP 28: Create Documentation

File: docs/ManagedBehaviour_Usage_Guide.md

Content:

  1. Quick start guide
  2. Common patterns and examples
  3. Lifecycle phase reference
  4. Priority guidelines
  5. Performance considerations
  6. Migration guide from MonoBehaviour
  7. Troubleshooting section

File: docs/ManagedBehaviour_API_Reference.md

Content:

  1. Complete API documentation
  2. All virtual methods with parameters
  3. All properties and their defaults
  4. Integration points (SaveLoadManager, GameManager)
  5. Best practices

File: docs/ManagedBehaviour_Architecture.md

Content:

  1. System architecture diagram
  2. Component interaction flows
  3. Performance characteristics
  4. Design decisions and rationale
  5. Future extension points

STEP 29: Performance Optimization Pass

File: Assets/Scripts/Core/Lifecycle/LifecycleManager.cs

Actions:

  1. Profile Update/FixedUpdate broadcasts
  2. Consider using Unity Jobs for parallel execution (if applicable)
  3. Add object pooling for event subscriptions
  4. Cache frequently accessed lists
  5. Add compile-time flags for debug features
  6. Optimize sort algorithms for registration
  7. Consider lazy initialization for empty lists

Targets:

  • Registration: < 0.1ms per component
  • Update broadcast: < 0.5ms for 100 components
  • Memory overhead: < 100 bytes per ManagedBehaviour

Key Details:

  • Use Unity Profiler to identify bottlenecks
  • Compare against baseline (vanilla MonoBehaviour)
  • Optimize hot paths (Update broadcasts)

STEP 30: Create Editor Tools

File: Assets/Editor/LifecycleManagerInspector.cs

Actions:

  1. Custom inspector for LifecycleManager
  2. Show registered components grouped by phase
  3. Display component priorities
  4. Show current state flags
  5. Add "Force Broadcast" buttons for testing
  6. Real-time component count display

File: Assets/Editor/ManagedBehaviourInspector.cs

Actions:

  1. Custom inspector for ManagedBehaviour
  2. Show active lifecycle phases (visual flags)
  3. Display current registration status
  4. Show priority values
  5. List registered managed events
  6. Add "Test Lifecycle" button

File: Assets/Editor/LifecycleDebugWindow.cs

Actions:

  1. Custom editor window "Window/Lifecycle/Debug"
  2. Real-time lifecycle event log
  3. Component hierarchy view
  4. Priority visualization
  5. Performance metrics
  6. Event subscription viewer

STEP 31: Final Integration Testing

Test Scenarios:

  1. Boot Sequence Test:

    • Start game from BootstrapScene
    • Verify all lifecycle phases execute in order
    • Check priority ordering is respected
    • Validate settings load correctly
  2. Scene Transition Test:

    • Switch between multiple scenes
    • Verify OnSceneReady called for new scenes
    • Verify OnSceneUnloading called for old scenes
    • Check persistent components don't receive scene events
  3. Save/Load Test:

    • Save game state
    • Switch scenes
    • Load saved state
    • Verify all ISaveParticipant components restored
  4. Pause System Test:

    • Pause game (multiple requests)
    • Verify all pausable components paused
    • Resume game
    • Verify all components resumed
  5. Late Registration Test:

    • Instantiate ManagedBehaviour after boot
    • Verify it receives appropriate lifecycle calls
    • Check it gets current state (paused, scene ready, etc.)
  6. Destruction Test:

    • Destroy ManagedBehaviours during gameplay
    • Verify cleanup happens correctly
    • Check no memory leaks (event subscriptions cleaned)
  7. Performance Test:

    • Spawn 100+ ManagedBehaviours
    • Measure frame time impact
    • Profile Update broadcasts
    • Check memory usage

STEP 32: Migration Strategy for Remaining Components

Approach: Gradual, category-by-category migration

Phase 1: Critical Path (Already covered in steps 20-25)

  • Core managers
  • UI systems
  • Gameplay systems

Phase 2: Scene-Specific Components

  • Level switches
  • Minigame components
  • Puzzle elements
  • Scene triggers

Phase 3: Utility Components

  • Camera systems
  • Audio managers
  • Effect spawners
  • Pooling systems

Phase 4: Low-Priority/External

  • Experimental scripts
  • Test components
  • External plugin wrappers

For Each Component:

  1. Assess if it benefits from ManagedBehaviour (needs lifecycle control?)
  2. If yes: follow migration pattern (change base class, update hooks)
  3. If no: leave as MonoBehaviour (simple utility scripts)
  4. Test after each file migrated
  5. Commit to version control

Key Details:

  • Not all components need migration (only those needing lifecycle control)
  • Prioritize components with InitializePostBoot, scene event subscriptions, or complex initialization
  • Simple components (visual effects, UI elements) can stay MonoBehaviour
  • Document migration decisions in code comments

STEP 33: Backward Compatibility Layer

File: Assets/Scripts/Core/Lifecycle/LegacyMonoBehaviourAdapter.cs

Actions:

  1. Create adapter class for existing MonoBehaviour components
  2. Allows non-migrated components to participate in lifecycle
  3. Implement manual registration helper:
    public static class LifecycleHelper
    {
        public static void RegisterLegacyComponent(MonoBehaviour component, Action onBootComplete)
        {
            BootCompletionService.RegisterInitAction(onBootComplete);
        }
    }
    
  4. Document when to use adapter vs. migration

Key Details:

  • Provides bridge during migration period
  • Allows incremental adoption
  • Eventually can be deprecated once migration complete

STEP 34: Code Cleanup and Refactoring

Actions:

  1. Remove Redundant Code:

    • Search for BootCompletionService.RegisterInitAction in migrated files (should be removed)
    • Search for manual event subscription patterns (Convert to RegisterManagedEvent)
    • Remove empty InitializePostBoot methods
  2. Standardize Patterns:

    • Consistent priority values across similar components
    • Consistent ActiveLifecyclePhases usage
    • Consistent logging patterns
  3. Update Comments:

    • Remove outdated references to old lifecycle
    • Add references to ManagedBehaviour lifecycle
    • Document priority decisions
  4. Code Review:

    • Review all migrated files
    • Check for proper base.OnManagedAwake() calls
    • Verify no breaking changes to public APIs

STEP 35: Update Project Documentation

Files to Update:

  1. docs/bootstrap_readme.md:

    • Add section on ManagedBehaviour integration
    • Update lifecycle flow diagrams
    • Reference new lifecycle guide
  2. README.md:

    • Add link to ManagedBehaviour documentation
    • Update project structure description
  3. Create docs/ManagedBehaviour_Migration_Log.md:

    • List of migrated components
    • Migration dates
    • Issues encountered and solutions
    • Components intentionally not migrated
  4. Update inline documentation:

    • Update XML comments in migrated files
    • Reference ManagedBehaviour lifecycle in comments
    • Add examples where helpful

STEP 36: Performance Profiling and Optimization

Actions:

  1. Baseline Measurements:

    • Measure current performance (before optimization)
    • Profile Update broadcasts (100+ components)
    • Memory allocation tracking
    • GC pressure measurement
  2. Optimization Targets:

    • LifecycleManager.Update < 0.5ms (100 components)
    • LifecycleManager.FixedUpdate < 0.3ms (100 components)
    • Registration < 0.1ms per component
    • Zero GC allocations during broadcasts
  3. Implementation:

    • Cache component counts
    • Use for loops instead of foreach (no allocator)
    • Avoid boxing in generic methods
    • Pool event subscription objects
    • Use struct enumerators
  4. Validation:

    • Re-profile after optimizations
    • Compare against baseline
    • Ensure optimizations don't break functionality

STEP 37: Edge Case Handling

Scenarios to Handle:

  1. Editor Mode:

    • Handle domain reload
    • Handle enter/exit play mode
    • Handle script recompilation during play
  2. Build Scenarios:

    • Development builds (debug logging enabled)
    • Release builds (debug code stripped)
    • Platform-specific behavior
  3. Error Recovery:

    • Handle missing LifecycleManager gracefully
    • Handle null component references
    • Handle exceptions during lifecycle hooks (isolate failures)
  4. Threading:

    • Ensure thread safety for registration queue
    • Handle registration from background threads (queue for main thread)
  5. Scene Edge Cases:

    • Handle multiple scenes loaded additively
    • Handle rapid scene switches
    • Handle scene unload during lifecycle broadcast

Implementation: Add defensive checks, logging, and fallbacks throughout LifecycleManager and ManagedBehaviour.


STEP 38: Create Tutorial Scene

File: Assets/Scenes/ManagedBehaviourTutorial.unity

Actions:

  1. Create tutorial scene demonstrating system
  2. Include examples of:
    • Simple ManagedBehaviour
    • Priority ordering demonstration
    • Lifecycle phase visualization
    • Event subscription examples
    • Save/load integration
    • Pause system integration
  3. Add UI showing lifecycle events in real-time
  4. Include interactive elements to trigger phases

File: Assets/Scripts/Tutorial/LifecycleEventLogger.cs

Actions:

  1. Create component that logs all lifecycle events to UI
  2. Shows order of execution
  3. Shows timing information
  4. Color-codes by priority

STEP 39: Community Documentation and Examples

File: docs/ManagedBehaviour_FAQ.md

Content:

  1. Frequently asked questions
  2. Common mistakes and solutions
  3. When to use ManagedBehaviour vs MonoBehaviour
  4. Performance considerations
  5. Debugging tips

File: docs/ManagedBehaviour_Recipes.md

Content:

  1. Common patterns and recipes
  2. Singleton pattern with ManagedBehaviour
  3. Scene-specific manager pattern
  4. Persistent service pattern
  5. Component with managed events pattern
  6. Save/load participant pattern

STEP 40: Final Review and Release Preparation

Checklist:

  • All core systems migrated
  • All tests passing
  • Performance targets met
  • Documentation complete
  • Examples created and tested
  • Editor tools working
  • No console errors or warnings
  • Code reviewed
  • Backward compatibility maintained
  • Migration guide complete

Final Actions:

  1. Create release notes
  2. Tag version in git
  3. Update project version number
  4. Create migration checklist for team
  5. Schedule team training/walkthrough
  6. Monitor for issues after deployment

Appendix A: Priority Guidelines

Component Type Priority Range Reasoning
Core Infrastructure 0-20 LifecycleManager, CustomBoot integration
Core Managers 10-30 GameManager, SceneManager, SaveManager
Service Providers 30-50 Settings providers, factories
Gameplay Managers 50-100 PuzzleManager, CardSystem, Minigames
UI Controllers 100-150 Page controllers, loading screens
Scene Components 150-200 Level-specific logic
Gameplay Objects 200-500 Interactables, pickups, NPCs
Visual Effects 500-1000 Particles, animations, decorative

Priority Best Practices

  • Use increments of 5 or 10 for easy insertion
  • Document priority decisions in code comments
  • Avoid priority 0 (reserved for system use)
  • Group related components in same priority range
  • Consider dependencies when assigning priorities

Appendix B: Common Migration Patterns

Pattern 1: Basic Singleton Manager

Before:

public class MyManager : MonoBehaviour
{
    private static MyManager _instance;
    public static MyManager Instance => _instance;
    
    void Awake()
    {
        _instance = this;
        BootCompletionService.RegisterInitAction(InitializePostBoot);
    }
    
    private void InitializePostBoot()
    {
        // Setup
    }
}

After:

public class MyManager : ManagedBehaviour
{
    private static MyManager _instance;
    public static MyManager Instance => _instance;
    
    protected override int BootCompletePriority => 50;
    protected override LifecycleFlags ActiveLifecyclePhases => 
        LifecycleFlags.ManagedAwake | LifecycleFlags.BootComplete;
    
    protected override void OnManagedAwake()
    {
        _instance = this;
    }
    
    protected override void OnBootComplete()
    {
        // Setup
    }
}

Pattern 2: Component with Event Subscriptions

Before:

public class MyComponent : MonoBehaviour
{
    void Start()
    {
        SomeManager.Instance.OnEvent += HandleEvent;
    }
    
    void OnDestroy()
    {
        if (SomeManager.Instance != null)
            SomeManager.Instance.OnEvent -= HandleEvent;
    }
    
    private void HandleEvent() { }
}

After:

public class MyComponent : ManagedBehaviour
{
    protected override LifecycleFlags ActiveLifecyclePhases => 
        LifecycleFlags.BootComplete;
    
    protected override void OnBootComplete()
    {
        RegisterManagedEvent(SomeManager.Instance, 
            m => m.OnEvent += HandleEvent);
    }
    
    private void HandleEvent() { }
    // No OnDestroy needed - auto cleanup
}

Pattern 3: Scene-Specific Component

Before:

public class LevelComponent : MonoBehaviour
{
    void Start()
    {
        SceneManagerService.Instance.SceneLoadCompleted += OnSceneLoaded;
        Initialize();
    }
    
    void OnDestroy()
    {
        if (SceneManagerService.Instance != null)
            SceneManagerService.Instance.SceneLoadCompleted -= OnSceneLoaded;
    }
    
    private void OnSceneLoaded(string sceneName) { }
    private void Initialize() { }
}

After:

public class LevelComponent : ManagedBehaviour
{
    protected override LifecycleFlags ActiveLifecyclePhases => 
        LifecycleFlags.SceneReady | LifecycleFlags.SceneUnloading;
    
    protected override void OnSceneReady()
    {
        Initialize();
    }
    
    protected override void OnSceneUnloading()
    {
        Cleanup();
    }
    
    private void Initialize() { }
    private void Cleanup() { }
}

Appendix C: Troubleshooting Guide

Issue: Lifecycle hook not being called

Symptoms: OnBootComplete or other hook not executing Solutions:

  1. Check ActiveLifecyclePhases includes the appropriate flag
  2. Verify LifecycleManager exists in scene
  3. Ensure base.OnManagedAwake() called if overriding
  4. Check LifecycleManager debug logs

Issue: Wrong execution order

Symptoms: Components initialize in unexpected order Solutions:

  1. Verify priority values (lower = earlier)
  2. Check for priority conflicts (same priority = undefined order)
  3. Add debug logging to verify execution order
  4. Use LifecycleDebugWindow to visualize order

Issue: Events not cleaning up

Symptoms: Memory leaks or errors after component destruction Solutions:

  1. Use RegisterManagedEvent instead of manual subscription
  2. Verify OnDestroy calls base.OnDestroy()
  3. Check event target is not null when registering
  4. Review LifecycleManager event cleanup logs

Issue: Performance degradation

Symptoms: Frame time increases with many ManagedBehaviours Solutions:

  1. Only override lifecycle hooks you need
  2. Don't use OnManagedUpdate if Unity Update suffices
  3. Profile with Unity Profiler to find bottleneck
  4. Check for excessive logging in release builds
  5. Optimize ActiveLifecyclePhases (don't include unused phases)

Appendix D: Integration Checklist

Use this checklist when migrating each component:

Pre-Migration:

  • Component has InitializePostBoot or complex initialization
  • Component subscribes to manager events
  • Component needs deterministic initialization order
  • Component is ISaveParticipant or IPausable

Migration:

  • Changed base class to ManagedBehaviour
  • Set appropriate priority values
  • Added ActiveLifecyclePhases flags
  • Moved Awake logic to OnManagedAwake
  • Moved InitializePostBoot to OnBootComplete
  • Converted event subscriptions to RegisterManagedEvent
  • Removed manual BootCompletionService registration
  • Set AutoRegisterSaveParticipant if ISaveParticipant
  • Set AutoRegisterPausable if IPausable
  • Updated XML documentation

Post-Migration:

  • No compiler errors
  • Component still functions correctly
  • Lifecycle hooks called at appropriate times
  • Priority ordering correct relative to dependencies
  • No memory leaks (events cleaned up)
  • Performance acceptable
  • Code reviewed
  • Tests updated/added

Appendix E: Future Enhancements

Potential future additions to the system:

  1. Async Lifecycle Hooks: Support for async/await in lifecycle methods
  2. Conditional Phases: Enable/disable phases at runtime
  3. Lifecycle Groups: Group related components for batch operations
  4. Visual Editor: Node-based lifecycle flow visualization
  5. Hot Reload Support: Better handling of domain reload in editor
  6. Multi-threading: Parallel execution of independent components
  7. Lifecycle Templates: Pre-configured setups for common patterns
  8. Analytics Integration: Track lifecycle performance in production
  9. Memory Pooling: Pool ManagedBehaviour instances for performance
  10. Dependency Injection: Auto-resolve dependencies in OnManagedAwake

Document Metadata

Version: 1.0
Last Updated: October 30, 2025
Author: AI Assistant
Status: Ready for Implementation

Implementation Estimate: 40-60 hours across 2-3 weeks
Risk Level: Medium (significant refactoring, but incremental approach reduces risk)
Prerequisites: Unity 2021.3+, C# 8.0+, existing bootstrap system

Next Steps:

  1. Review this document thoroughly
  2. Get team approval
  3. Begin with STEP 1
  4. Progress sequentially through steps
  5. Test thoroughly at each phase
  6. Document any deviations or issues