public static SaveFile CreateSaveFileFromCurrentState(string saveFileName) { // We force the ManagerScene to find all SaveableObjects because of the ExecuteInEditMode scripts in this scene SaveManagerForScene managerSceneSaveManager = SaveManager.saveManagers[LevelManager.ManagerScene]; managerSceneSaveManager.ForceGetAllSaveableObjectsInScene(); return(new SaveFile { saveFileName = saveFileName, managerScene = SaveManager.saveManagers[LevelManager.ManagerScene].GetSaveFileForScene(), scenes = SaveManager.saveManagers .Where(kv => kv.Key != LevelManager.ManagerScene) .ToDictionary(kv => kv.Key, kv => kv.Value.GetSaveFileForScene()), dynamicObjects = DynamicObjectManager.GetDynamicObjectRecordsSave() }); }
void ChangeScene(Scene newScene) { if (isGlobal && gameObject.scene != newScene) { // Deregister the DynamicObject in the old SaveManagerForScene SaveForScene.UnregisterDynamicObject(ID); gameObject.transform.SetParent(null); // Move the GameObject to the new scene SceneManager.MoveGameObjectToScene(gameObject, newScene); // Update the record of the DynamicObject in DynamicObjectManager DynamicObjectManager.ChangeDynamicObjectScene(this, SceneName); // Re-register the DynamicObject in the new SaveManagerForScene SaveForScene.RegisterDynamicObject(this); } }
// DynamicObject.Destroy should be used instead of Object.Destroy to ensure proper record keeping // for when the object is explicitly destroyed (not just from a scene change, etc) public void Destroy() { bool unregistered = SaveForScene.UnregisterDynamicObject(ID); bool markedAsDestroyed = DynamicObjectManager.MarkDynamicObjectAsDestroyed(this, SceneName); if (unregistered && markedAsDestroyed) { debug.Log($"Marked as Destroyed in scene {SceneName}"); } else { debug.LogError($"Failed in Destroy. Unregistration successful: {unregistered}, Marked as destroyed successful: {markedAsDestroyed}"); } // Unregister any other SaveableObject scripts that may have existed on this object SaveForScene.UnregisterAllAssociatedObjects(ID); Destroy(gameObject); }
public void Register() { if (this == null || hasRegistered) { return; } RegistrationStatus dynamicObjectRegistrationStatus = DynamicObjectManager.RegisterDynamicObject(this, SceneName); bool dynamicObjectManagerRegistered = dynamicObjectRegistrationStatus.IsSuccess() || (SaveManager.isCurrentlyLoadingSave && !dynamicObjectRegistrationStatus.IsAlreadyDestroyed()); if (dynamicObjectManagerRegistered) { SaveForScene.RegisterDynamicObject(this); debug.Log($"Registration succeeded for {this.name}, scene {SceneName}"); hasRegistered = true; } else { debug.LogError($"Registration failed. DynamicObjectManager registration result: {dynamicObjectManagerRegistered}"); Destroy(gameObject); } }
public static async void Load(string saveName) { Debug.Log($"--- Loading Save File: {saveName} ---"); isCurrentlyLoadingSave = true; if (LevelManager.instance.IsCurrentlyLoadingScenes || LevelManager.instance.isCurrentlySwitchingScenes) { Debug.Log("Waiting for in-progress scene loading to finish before starting load..."); await TaskEx.WaitUntil(() => !LevelManager.instance.IsCurrentlyLoadingScenes && !LevelManager.instance.isCurrentlySwitchingScenes); } MainCanvas.instance.blackOverlayState = MainCanvas.BlackOverlayState.On; Time.timeScale = 0f; // Clear out existing DynamicObjects so they don't stick around when the new save file is loaded DynamicObjectManager.DeleteAllExistingDynamicObjectsAndClearState(); // Get the save file from disk SaveFile save = SaveFile.RetrieveSaveFileFromDisk(saveName); // Create a SaveManager for ManagerScene and restore its state SaveManagerForScene saveManagerForManagerScene = GetOrCreateSaveManagerForScene(LevelManager.ManagerScene); saveManagerForManagerScene.LoadSaveableObjectsStateFromSaveFile(save.managerScene); Debug.Log("Waiting for scenes to be loaded..."); await TaskEx.WaitUntil(() => !LevelManager.instance.IsCurrentlyLoadingScenes); Debug.Log("All scenes loaded into memory, loading save..."); // Load records of all DynamicObjects from disk save.dynamicObjects.LoadSaveFile(); // Load all DynamicObjects for each scene foreach (var kv in save.scenes) { string sceneName = kv.Key; SaveFileForScene saveFileForScene = kv.Value; SaveManagerForScene saveManager = GetOrCreateSaveManagerForScene(sceneName); saveManager.LoadDynamicObjectsStateFromSaveFile(saveFileForScene); } Dictionary <string, SaveFileForScene> loadedScenes = save.scenes .Where(kv => LevelManager.instance.loadedSceneNames.Contains(kv.Key)) .ToDictionary(); Dictionary <string, SaveFileForScene> unloadedScenes = save.scenes .Except(loadedScenes) .ToDictionary(); // Restore state for all unloaded scenes from the save file foreach (var kv in unloadedScenes) { string sceneName = kv.Key; SaveFileForScene saveFileForScene = kv.Value; SaveManagerForScene saveManager = GetOrCreateSaveManagerForScene(sceneName); saveManager.LoadSaveableObjectsStateFromSaveFile(saveFileForScene); } // Load data for every object in each loaded scene (starting with the ManagerScene) saveManagerForManagerScene.LoadSaveableObjectsStateFromSaveFile(save.managerScene); foreach (var kv in loadedScenes) { string sceneName = kv.Key; SaveFileForScene saveFileForScene = kv.Value; SaveManagerForScene saveManager = GetOrCreateSaveManagerForScene(sceneName); saveManager.LoadSaveableObjectsStateFromSaveFile(saveFileForScene); } // Play the level change banner and remove the black overlay LevelChangeBanner.instance.PlayBanner(LevelManager.instance.ActiveScene); Time.timeScale = 1f; MainCanvas.instance.blackOverlayState = MainCanvas.BlackOverlayState.FadingOut; isCurrentlyLoadingSave = false; }
// Similar to DynamicObject.Destroy but for objects in unloaded scenes public override void Destroy() { base.Destroy(); DynamicObjectManager.MarkDynamicObjectAsDestroyed(this, scene); }