/// <summary> /// Whenever another scene is loaded, we have another shot at resolving more cross-scene references /// </summary> /// <param name="sceneSetup">The AmsMultiSceneSetup that was loaded</param> private void HandleNewSceneLoaded(AmsMultiSceneSetup sceneSetup) { var loadedScene = sceneSetup.gameObject.scene; if (!loadedScene.isLoaded) { Debug.LogErrorFormat(this, "{0} Received HandleNewSceneLoaded from scene {1} which isn't considered loaded. The scene MUST be considered loaded by this point", GetType().Name, loadedScene.name); } // Restore any references to this newly loaded scene for (int i = 0; i < _crossSceneReferences.Count; ++i) { var xRef = _crossSceneReferences[i]; if (!xRef.fromObject) { AmsDebug.LogWarning(this, "xRef Index {0} had Null source (probably stale), Consider removing (via right-click on entry)", i); continue; } if (!_referencesToResolve.Contains(xRef) && xRef.toScene.scene == loadedScene) { _referencesToResolve.Add(xRef); } } if (_referencesToResolve.Count > 0) { AmsDebug.Log(this, "Scene {0} Loaded. {1} Cross-Scene References (in total) from Cross-Scene Manager in {2} are queued for resolve.", loadedScene.name, _referencesToResolve.Count, gameObject.scene.name); ConditionalResolveReferences(_referencesToResolve); } }
/// <summary> /// This is called during the build pipeline to ensure a proper merge from one scene into another, taking into account cross-scene references /// </summary> /// <param name="sourceSceneSetup">The scene we're merging from</param> /// <param name="destSceneSetup">The scene we're merging to</param> public static void EditorBuildPipelineMergeScene(AmsMultiSceneSetup sourceSceneSetup, AmsMultiSceneSetup destSceneSetup) { // This is happening during the build system, so we're going to end up with a scene name of 0.backup // So we need to get the actual path from the AmsMultiSceneSetup object and clobber it. var amsFromSceneRef = new AmsSceneReference(sourceSceneSetup.gameObject.scene); amsFromSceneRef.editorPath = sourceSceneSetup.scenePath; var amsIntoSceneRef = new AmsSceneReference(destSceneSetup.gameObject.scene); amsIntoSceneRef.editorPath = destSceneSetup.scenePath; // Now get the cross-scene references from both scenes to merge them var srcCrossSceneRefs = GetSceneSingleton(sourceSceneSetup.gameObject.scene, false); if (!srcCrossSceneRefs) { return; } var destCrossSceneRefs = GetSceneSingleton(destSceneSetup.gameObject.scene, true); for (int i = 0; i < srcCrossSceneRefs._crossSceneReferences.Count; ++i) { var xRef = srcCrossSceneRefs._crossSceneReferences[i]; if (!srcCrossSceneRefs._referencesToResolve.Contains(xRef)) { AmsDebug.Log(srcCrossSceneRefs, "Already resolved xRef {0}. No need to merge it.", xRef); continue; } AmsDebug.Log(destSceneSetup, "Merging {0} into Scene {1}", xRef, amsIntoSceneRef.editorPath); xRef.DEPRECATED_fromScene = amsIntoSceneRef; destCrossSceneRefs.AddReference(xRef); } // Mark this as a merged scene in the destination, so when we look-up cross-scene references we're aware. destCrossSceneRefs._mergedScenes.Add(amsFromSceneRef); // Destroy this object after the merge is complete (we don't want it merged into the scene) GameObject.DestroyImmediate(srcCrossSceneRefs.gameObject, false); }
/// <summary> /// Whenever another scene is loaded, we have another shot at resolving more cross-scene references /// </summary> /// <param name="sceneSetup">The AmsMultiSceneSetup that was loaded</param> private void HandleNewSceneLoaded(AmsMultiSceneSetup sceneSetup) { var loadedScene = sceneSetup.gameObject.scene; if (!Application.isPlaying) { // Restore any references to this newly loaded scene foreach (var xRef in _crossSceneReferences) { if (!_referencesToResolve.Contains(xRef) && xRef.toScene.scene == loadedScene) { _referencesToResolve.Add(xRef); } } } if (_referencesToResolve.Count > 0) { AmsDebug.Log(this, "Scene {0} Loaded. {1} Cross-Scene References are queued for resolve.", loadedScene.name, _referencesToResolve.Count); StartCoroutine(CoWaitForSceneLoadThenResolveReferences(loadedScene)); } }
/// <summary> /// Whenever a scene is destroyed, we will receive this callback. In the editor, we can remember that we may be about to lose a cross-scene reference. /// </summary> /// <param name="sceneSetup"></param> private void HandleSceneDestroyed(AmsMultiSceneSetup sceneSetup) { var destroyedScene = sceneSetup.gameObject.scene; if (!destroyedScene.IsValid()) { return; } // If our own scene is being destroyed, we don't need to do anymore work if (destroyedScene == gameObject.scene) { return; } // Remove all of the pending refs for that scene. _referencesToResolve.RemoveAll(x => x.toScene.scene == destroyedScene); // Now we re-add all of the relevant refs to pending. They'll be re-resolved when the scene is loaded again. var allRelevantRefs = _crossSceneReferences.Where(x => x.toScene.scene == destroyedScene); _referencesToResolve.AddRange(allRelevantRefs); }
/// <summary> /// Whenever another scene is loaded, we have another shot at resolving more cross-scene references /// </summary> /// <param name="sceneSetup">The AmsMultiSceneSetup that was loaded</param> private void HandleNewSceneLoaded(AmsMultiSceneSetup sceneSetup) { var loadedScene = sceneSetup.gameObject.scene; if (!loadedScene.isLoaded) { Debug.LogErrorFormat(this, "{0} Received HandleNewSceneLoaded from scene {1} which isn't considered loaded. The scene MUST be considered loaded by this point", GetType().Name, loadedScene.name); } // Restore any references to this newly loaded scene foreach (var xRef in _crossSceneReferences) { if (!_referencesToResolve.Contains(xRef) && xRef.toScene.scene == loadedScene) { _referencesToResolve.Add(xRef); } } if (_referencesToResolve.Count > 0) { AmsDebug.Log(this, "Scene {0} Loaded. {1} Cross-Scene References (in total) from Cross-Scene Manager in {2} are queued for resolve.", loadedScene.name, _referencesToResolve.Count, gameObject.scene.name); ConditionalResolveReferences(_referencesToResolve); } }
/// <summary> /// Whenever a scene is destroyed, we will receive this callback. In the editor, we can remember that we may be about to lose a cross-scene reference. /// </summary> /// <param name="sceneSetup"></param> private void HandleSceneDestroyed( AmsMultiSceneSetup sceneSetup ) { var destroyedScene = sceneSetup.gameObject.scene; if ( !destroyedScene.IsValid() ) return; // If our own scene is being destroyed, we don't need to do anymore work if ( destroyedScene == gameObject.scene ) return; // Remove all of the pending refs for that scene. _referencesToResolve.RemoveAll( x => x.toScene.scene == destroyedScene ); // Now we re-add all of the relevant refs to pending. They'll be re-resolved when the scene is loaded again. var allRelevantRefs = _crossSceneReferences.Where( x => x.toScene.scene == destroyedScene ); _referencesToResolve.AddRange( allRelevantRefs ); }
/// <summary> /// Whenever another scene is loaded, we have another shot at resolving more cross-scene references /// </summary> /// <param name="sceneSetup">The AmsMultiSceneSetup that was loaded</param> private void HandleNewSceneLoaded( AmsMultiSceneSetup sceneSetup ) { var loadedScene = sceneSetup.gameObject.scene; if ( !loadedScene.isLoaded ) Debug.LogErrorFormat( this, "{0} Received HandleNewSceneLoaded from scene {1} which isn't considered loaded. The scene MUST be considered loaded by this point", GetType().Name, loadedScene.name ); // Restore any references to this newly loaded scene foreach( var xRef in _crossSceneReferences ) { if ( !_referencesToResolve.Contains(xRef) && xRef.toScene.scene == loadedScene ) _referencesToResolve.Add( xRef ); } if ( _referencesToResolve.Count > 0 ) { AmsDebug.Log( this, "Scene {0} Loaded. {1} Cross-Scene References (in total) from Cross-Scene Manager in {2} are queued for resolve.", loadedScene.name, _referencesToResolve.Count, gameObject.scene.name ); ConditionalResolveReferences( _referencesToResolve ); } }