# Lifecycle Management & Save System Revamp
## Overview
Complete overhaul of game lifecycle management, interactable system, and save/load architecture. Introduces centralized `ManagedBehaviour` base class for consistent initialization ordering and lifecycle hooks across all systems.
## Core Architecture
### New Lifecycle System
- **`LifecycleManager`**: Centralized coordinator for all managed objects
- **`ManagedBehaviour`**: Base class replacing ad-hoc initialization patterns
- `OnManagedAwake()`: Priority-based initialization (0-100, lower = earlier)
- `OnSceneReady()`: Scene-specific setup after managers ready
- Replaces `BootCompletionService` (deleted)
- **Priority groups**: Infrastructure (0-20) → Game Systems (30-50) → Data (60-80) → UI/Gameplay (90-100)
- **Editor support**: `EditorLifecycleBootstrap` ensures lifecycle works in editor mode
### Unified SaveID System
- Consistent format: `{ParentName}_{ComponentType}`
- Auto-registration via `AutoRegisterForSave = true`
- New `DebugSaveIds` editor tool for inspection
## Save/Load Improvements
### Enhanced State Management
- **Extended SaveLoadData**: Unlocked minigames, card collection states, combination items, slot occupancy
- **Async loading**: `ApplyCardCollectionState()` waits for card definitions before restoring
- **New `SaveablePlayableDirector`**: Timeline sequences save/restore playback state
- **Fixed race conditions**: Proper initialization ordering prevents data corruption
## Interactable & Pickup System
- Migrated to `OnManagedAwake()` for consistent initialization
- Template method pattern for state restoration (`RestoreInteractionState()`)
- Fixed combination item save/load bugs (items in slots vs. follower hand)
- Dynamic spawning support for combined items on load
- **Breaking**: `Interactable.Awake()` now sealed, use `OnManagedAwake()` instead
## UI System Changes
- **AlbumViewPage** and **BoosterNotificationDot**: Migrated to `ManagedBehaviour`
- **Fixed menu persistence bug**: Menus no longer reappear after scene transitions
- **Pause Menu**: Now reacts to all scene loads (not just first scene)
- **Orientation Enforcer**: Enforces per-scene via `SceneManagementService`
- **Loading Screen**: Integrated with new lifecycle
## ⚠️ Breaking Changes
1. **`BootCompletionService` removed** → Use `ManagedBehaviour.OnManagedAwake()` with priority
2. **`Interactable.Awake()` sealed** → Override `OnManagedAwake()` instead
3. **SaveID format changed** → Now `{ParentName}_{ComponentType}` consistently
4. **MonoBehaviours needing init ordering** → Must inherit from `ManagedBehaviour`
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com>
Reviewed-on: #51
145 lines
3.9 KiB
Plaintext
145 lines
3.9 KiB
Plaintext
%YAML 1.1
|
|
%TAG !u! tag:unity3d.com,2011:
|
|
--- !u!1 &825072831861764844
|
|
GameObject:
|
|
m_ObjectHideFlags: 0
|
|
m_CorrespondingSourceObject: {fileID: 0}
|
|
m_PrefabInstance: {fileID: 0}
|
|
m_PrefabAsset: {fileID: 0}
|
|
serializedVersion: 6
|
|
m_Component:
|
|
- component: {fileID: 25208727450420889}
|
|
- component: {fileID: 8318004605383042340}
|
|
- component: {fileID: 4266110216568578813}
|
|
- component: {fileID: 1707774147108908574}
|
|
m_Layer: 10
|
|
m_Name: YellowBall
|
|
m_TagString: Untagged
|
|
m_Icon: {fileID: 0}
|
|
m_NavMeshLayer: 0
|
|
m_StaticEditorFlags: 0
|
|
m_IsActive: 1
|
|
--- !u!4 &25208727450420889
|
|
Transform:
|
|
m_ObjectHideFlags: 0
|
|
m_CorrespondingSourceObject: {fileID: 0}
|
|
m_PrefabInstance: {fileID: 0}
|
|
m_PrefabAsset: {fileID: 0}
|
|
m_GameObject: {fileID: 825072831861764844}
|
|
serializedVersion: 2
|
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
m_ConstrainProportionsScale: 0
|
|
m_Children: []
|
|
m_Father: {fileID: 0}
|
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
--- !u!65 &8318004605383042340
|
|
BoxCollider:
|
|
m_ObjectHideFlags: 0
|
|
m_CorrespondingSourceObject: {fileID: 0}
|
|
m_PrefabInstance: {fileID: 0}
|
|
m_PrefabAsset: {fileID: 0}
|
|
m_GameObject: {fileID: 825072831861764844}
|
|
m_Material: {fileID: 0}
|
|
m_IncludeLayers:
|
|
serializedVersion: 2
|
|
m_Bits: 0
|
|
m_ExcludeLayers:
|
|
serializedVersion: 2
|
|
m_Bits: 0
|
|
m_LayerOverridePriority: 0
|
|
m_IsTrigger: 0
|
|
m_ProvidesContacts: 0
|
|
m_Enabled: 1
|
|
serializedVersion: 3
|
|
m_Size: {x: 1, y: 1, z: 1}
|
|
m_Center: {x: 0, y: 0, z: 0}
|
|
--- !u!212 &4266110216568578813
|
|
SpriteRenderer:
|
|
m_ObjectHideFlags: 0
|
|
m_CorrespondingSourceObject: {fileID: 0}
|
|
m_PrefabInstance: {fileID: 0}
|
|
m_PrefabAsset: {fileID: 0}
|
|
m_GameObject: {fileID: 825072831861764844}
|
|
m_Enabled: 1
|
|
m_CastShadows: 0
|
|
m_ReceiveShadows: 0
|
|
m_DynamicOccludee: 1
|
|
m_StaticShadowCaster: 0
|
|
m_MotionVectors: 1
|
|
m_LightProbeUsage: 1
|
|
m_ReflectionProbeUsage: 1
|
|
m_RayTracingMode: 0
|
|
m_RayTraceProcedural: 0
|
|
m_RayTracingAccelStructBuildFlagsOverride: 0
|
|
m_RayTracingAccelStructBuildFlags: 1
|
|
m_SmallMeshCulling: 1
|
|
m_ForceMeshLod: -1
|
|
m_MeshLodSelectionBias: 0
|
|
m_RenderingLayerMask: 1
|
|
m_RendererPriority: 0
|
|
m_Materials:
|
|
- {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2}
|
|
m_StaticBatchInfo:
|
|
firstSubMesh: 0
|
|
subMeshCount: 0
|
|
m_StaticBatchRoot: {fileID: 0}
|
|
m_ProbeAnchor: {fileID: 0}
|
|
m_LightProbeVolumeOverride: {fileID: 0}
|
|
m_ScaleInLightmap: 1
|
|
m_ReceiveGI: 1
|
|
m_PreserveUVs: 0
|
|
m_IgnoreNormalsForChartDetection: 0
|
|
m_ImportantGI: 0
|
|
m_StitchLightmapSeams: 1
|
|
m_SelectedEditorRenderState: 0
|
|
m_MinimumChartSize: 4
|
|
m_AutoUVMaxDistance: 0.5
|
|
m_AutoUVMaxAngle: 89
|
|
m_LightmapParameters: {fileID: 0}
|
|
m_GlobalIlluminationMeshLod: 0
|
|
m_SortingLayerID: 0
|
|
m_SortingLayer: 0
|
|
m_SortingOrder: 1
|
|
m_Sprite: {fileID: -4183208330383030991, guid: 26abd62d79d435f438c281aa83ee274a, type: 3}
|
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
|
m_FlipX: 0
|
|
m_FlipY: 0
|
|
m_DrawMode: 0
|
|
m_Size: {x: 0.76, y: 0.76}
|
|
m_AdaptiveModeThreshold: 0.5
|
|
m_SpriteTileMode: 0
|
|
m_WasSpriteAssigned: 1
|
|
m_MaskInteraction: 0
|
|
m_SpriteSortPoint: 1
|
|
--- !u!114 &1707774147108908574
|
|
MonoBehaviour:
|
|
m_ObjectHideFlags: 0
|
|
m_CorrespondingSourceObject: {fileID: 0}
|
|
m_PrefabInstance: {fileID: 0}
|
|
m_PrefabAsset: {fileID: 0}
|
|
m_GameObject: {fileID: 825072831861764844}
|
|
m_Enabled: 1
|
|
m_EditorHideFlags: 0
|
|
m_Script: {fileID: 11500000, guid: 7846448751da4bdbaaa5cb87890dca42, type: 3}
|
|
m_Name:
|
|
m_EditorClassIdentifier: AppleHillsScripts::Interactions.Pickup
|
|
isOneTime: 0
|
|
cooldown: -1
|
|
characterToInteract: 2
|
|
interactionStarted:
|
|
m_PersistentCalls:
|
|
m_Calls: []
|
|
interactionInterrupted:
|
|
m_PersistentCalls:
|
|
m_Calls: []
|
|
characterArrived:
|
|
m_PersistentCalls:
|
|
m_Calls: []
|
|
interactionComplete:
|
|
m_PersistentCalls:
|
|
m_Calls: []
|
|
itemData: {fileID: 11400000, guid: 3b1f3472171abc943bb099ce31d6fc7c, type: 2}
|
|
iconRenderer: {fileID: 4266110216568578813}
|