Search Unity

Advanced Multi-Scene - Now Available

Discussion in 'Assets and Asset Store' started by Jodon, Feb 2, 2016.

  1. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Thanks Bubsavvy! There are a few touch points that you can use to do this. Let me explain how the plug-in works a bit more and then we can decide how to go about introducing this feature:

    AmsMultiSceneSetup is the instance that lives in your scene per-scene. It keeps track of loading the scenes that are configured to load.

    AmsCrossSceneReferences is the instance that lives in your scene per-scene. It should be on the same GameObject as the AmsMultiSceneSetup and is responsible for storing the 'runtime' version of the cross-scene references.

    Option #1: Just Restoring Cross-Scene References.
    Whenever you load a scene in the Editor, the cross-scene references should automatically be restored. If they aren't, let me know as that's a bug. You can force a restore of all of the cross-scene references by grabbing the AmsCrossSceneReferences (use AmsCrossSceneReferences.GetSceneSingleton) and then call ResolvePendingCrossSceneReferences on that Behaviour.

    Option #2: Grabbing the (Already Saved) Runtime Serialization Info
    If you're just looking at the Cross Scene References that are saved, you can grab the AmsCrossSceneReferences as above, and we can expose _crossSceneReferences which is a list of RuntimeCrossSceneReferences.

    Option #3: Computing the Cross-Scene References at Edit-Time
    You can call AmsCrossSceneReferenceProcessor.GetCrossSceneReferencesForScenes to get the Editor cross-scene references for a scene. These are a bit easier to work with than RuntimeCrossSceneReferences as they're guaranteed to be resolved. You can force a save using AmsCrossSceneReferenceProcessor.SaveCrossSceneReferences.

    Option #4: Storing Custom Data & Restoring Custom Data
    There is a method where you can store your own data and do a custom restore of a cross-scene reference. You can take a look at AmsCrossSceneReferenceProcessor.AddCustomCrossSceneDataProcessor and in particular, AmsPlayableDirectorCrossSceneData which determines what data should be stored when saving. Then there's AmsPlayableDirectorResolver and AmsCinemachineResolver which determine how to restore the data at runtime.

    Option #5: Hijacking the Save Method
    In AmsSaveProcessor is where the actual saving gets done. You can either put some code in here, or we can expose an event in here.

    Option #6: Hooking Into the Restore Operation
    Hook into AmsMultiSceneSetup.OnAwake to be notified that a scene is loaded. I believe this fires before any of the built-in Unity notifications and the trick is to get your class registered to this first thing -- try RuntimeInitializeOnLoad to do that. You can inject cross-scene references into AmsCrossSceneReferences by using AddReference. Note that you should add these before AmsCrossSceneReferences gets its Awake called (use the logging to verify this is the case).

    Let me know if that helps and if you need another approach.
     
  2. Bubsavvy

    Bubsavvy

    Joined:
    Sep 18, 2017
    Posts:
    48
    Hey @Jodon,

    This is excellent I will look into all of this with the team and try to get it too work with your current framework before possibly editing code inside the plugin. Our team will play around with all of these options and get back to you once we have fleshed out much of the guts of our project that we have sitting on our backlog. If you have a github or bitbucket maybe we can sink up and have you vet any additional code we add to your plugin for use in our game as well as others. Thanks for all the help and such a great tool. :D

    Cheers from Trollhousegames.
     
  3. stalhandske

    stalhandske

    Joined:
    Mar 17, 2014
    Posts:
    24
    Hi there. Just got this and looking forward to using it's scene cross referencing. Just wanted to poke you with an error that occur whenever I save. Don't know if I should be worried about it:


    The same field name is serialized multiple times in the class or its parent class. This is not supported: Base(MonoBehaviour) m_GameObject
    UnityEditor.SerializedObject:.ctor(Object)
    CodingJar.MultiScene.Editor.AmsCrossSceneReferenceProcessor:populateReferenceMap(List`1, IEnumerable`1) (at Assets/Plugins/CodingJar/MultiScene/Editor/AmsCrossSceneReferenceProcessor.cs:120)
    CodingJar.MultiScene.Editor.AmsCrossSceneReferenceProcessor:UpdateReferencesMap() (at Assets/Plugins/CodingJar/MultiScene/Editor/AmsCrossSceneReferenceProcessor.cs:87)
    CodingJar.MultiScene.Editor.AmsCrossSceneReferenceProcessor:ComputeAllCrossSceneReferences() (at Assets/Plugins/CodingJar/MultiScene/Editor/AmsCrossSceneReferenceProcessor.cs:50)
    CodingJar.MultiScene.Editor.AmsCrossSceneReferenceProcessor:GetCrossSceneReferencesForScenes(IEnumerable`1) (at Assets/Plugins/CodingJar/MultiScene/Editor/AmsCrossSceneReferenceProcessor.cs:57)
    CodingJar.MultiScene.Editor.AmsSaveProcessor:HandleCrossSceneReferences(IList`1) (at Assets/Plugins/CodingJar/MultiScene/Editor/AmsSaveProcessor.cs:108)
    CodingJar.MultiScene.Editor.AmsSaveProcessor:EditorSceneManager_sceneSaving(Scene, String) (at Assets/Plugins/CodingJar/MultiScene/Editor/AmsSaveProcessor.cs:27)
    UnityEditor.SceneManagement.EditorSceneManager:Internal_SceneSaving(Scene, String)

    Hope this all works out. Seems like a great tool. Cheers.
     
  4. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Hey Stalhandske,

    That warning is from the Unity serialization system. It sounds like you probably have a derived class that is serializing the same variable as a base class. So something like this:


    class Base : MonoBehaviour {
    [SerializeField] string field;
    }

    class Derived : Base {
    [SerializeField] string field;
    }


    Could also happen if you're serializing a name that might be used by Unity (e.g. string m_Name). Cheers.
     
  5. stalhandske

    stalhandske

    Joined:
    Mar 17, 2014
    Posts:
    24
    Do you know if there's an easy way to find the specific variable that's a problem? I've been searching around a bit now and can't seem to find the culprit.
     
  6. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    You can try and catch the exception / error in the debugger. You can also try to just eliminate stuff in the scene until you narrow it down.
     
  7. Zeevex

    Zeevex

    Joined:
    Jan 15, 2018
    Posts:
    28
    Hello!
    I'm interested in this asset, but the situation i have at the moment is that i have a push/pull system for my character and objects in a scene which are both on seperate scenes(somewhat like limbo). and i'm making the object to be pulled a child of the player controller
    so i'm wondering if with this asset i'm able to reference and have it linked or placed as a child of the player controller?
    probably a silly question, as it does seem impossible to be able to parent and unparent objects across scenes..
     
  8. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Presumably this is all happening at runtime, not design time. My plugin helps you keep cross scene references at design time. If this is your only desired case, you don't even need my plugin:

    If you're already getting both scenes to load addictively, it's simply a case of calling Transform.SetParent on the child transform and passing in your PlayerController. If your issue is having a reference to the PlayerController, you can make a static variable in it that gets assigned in Awake. This assumes you only have one MyPlayerController:

    Code (CSharp):
    1. class MyPlacerController : MonoBehaviour
    2. {
    3.     public static MyPlayerController Instance;
    4.  
    5.     void Awake() { Instance = this; }
    6. }
    Then you can call PlayerController.Instance to get the reference from any code.

    What my plugin does is allow these references in the editor, so you don't have to do these sort of work-arounds. The litmus test is if you've never encountered an error in the editor that you can't save cross-scene references, then my plug-in isn't your solution.
     
  9. thanhle

    thanhle

    Joined:
    May 2, 2013
    Posts:
    162
    Advanced Multi-Scene make the The project takes too much time to play !
    before i use plugin : 1 minute 24 seconds to play the game in the unity
    after use plugin : 3 minute to play the game in the unity
    Even in my big scene , i need 10 minute to play with Advanced Multi-Scene

    It seems like it was calculating something before it officially played the game!
    Tell me why and how it can play the game faster in unity !
     
  10. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Hello, I responded to your e-mail yesterday:

    The plug-in will go through all of the objects in your scenes to check for cross-scene references before launching. Are you certain it's my plug-in that's causing the issue? You can make a back-up, delete my plug-in and try again to see if it's actually the cause. If it IS the cause, it's possible you have a ton of objects in your scene that need to be inspected for cross-scene references. Typically this only takes a second or two, but maybe you have a special case where there's millions of GameObjects in the scene?

    If it is determined that it's my plug-in that's causing the issue, restart your Editor. Then go to the Unity menu: Edit / Preferences... Then under the Multi-Scene tab, enable Verbose Logging and Performance Logging. After enabling those, hit Play so that it's logging exactly what's happening. After it's started, just shut down Unity and send me the editor log so I can see what the issue is. The log file can be found by reading this link: https://docs.unity3d.com/Manual/LogFiles.html.

    image.png
     
  11. NeedsLoomis

    NeedsLoomis

    Joined:
    Mar 22, 2017
    Posts:
    57
    Heya, I can't get the basic functionality to work (using 2018.2).

    Two scenes, main one (TestMain), and secondary (Test1). Main scene has a camera, second has a script with nothing in it but:

    Code (CSharp):
    1. public class GenericTestScript : MonoBehaviour
    2. {
    3.     public Camera cam;
    4. }
    Drag and drop the camera, hit save, and it gives the error

    Any ideas?
     
  12. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Hey, that's really odd. Are you using a different serialization system like Odin? Is TestMain still open when you're saving? That one it's resolving is correct, right? It's not a previously deleted one it's trying to resolve?

    We have two projects now on 2018.2.17f and we haven't experienced issues. Can you send me that basic project that's causing this issue? I'll take a look asap.
     
  13. NeedsLoomis

    NeedsLoomis

    Joined:
    Mar 22, 2017
    Posts:
    57
    Yeap, there's the problem. Is there a workaround for this?
     
  14. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Not sure. I haven't used it, can you send me the smallest repro case you have? I'll take a look.
     
  15. NeedsLoomis

    NeedsLoomis

    Joined:
    Mar 22, 2017
    Posts:
    57
    Ok, tried to make a simple Repo from a clean project, and the problem disappeared. Went back to my problem project and restripped everything out, being more careful to test with each removal, and it's cinemachine.

    On a clean project, as soon as I add the cinemachine package, AMS breaks. I can still send a repo if needed :)
     
  16. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Yes please. I actually have cinemachine as a test case so it would be great to see this issue and I'll fix it.
     
  17. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Bad code by me. Anyone using Cinemachine will want to follow this: Change AmsCinemachineResolver.HandleCrossSceneReference() to this code:

    Code (CSharp):
    1.         static bool HandleCrossSceneReference( RuntimeCrossSceneReference xRef )
    2.         {
    3.             MonoBehaviour cinemachineBehaviour = xRef.fromObject as MonoBehaviour;
    4.             if ( !cinemachineBehaviour || !cinemachineBehaviour.isActiveAndEnabled )
    5.                 return false;
    6.  
    7.             string nameSpace = cinemachineBehaviour.GetType().Namespace;
    8.             if ( string.IsNullOrEmpty(nameSpace) || !nameSpace.StartsWith( "Cinemachine" ) )
    9.                 return false;
    10.  
    11.             AmsDebug.LogWarning( xRef.fromObject, "xSceneRef on Cinemachine Behaviour: {0}. Disabling/Enabling to ensure pipeline is up to date.", xRef );
    12.             cinemachineBehaviour.enabled = false;
    13.             cinemachineBehaviour.enabled = true;
    14.  
    15.             return false;
    16.         }
    Fixed version is uploaded to the store and will be available soon.
     
    Last edited: Dec 11, 2018
  18. NeedsLoomis

    NeedsLoomis

    Joined:
    Mar 22, 2017
    Posts:
    57
  19. MoribitoMT

    MoribitoMT

    Joined:
    Jun 1, 2013
    Posts:
    301
    Hi,

    I am trying to find right asset for me, I have questions if this asset correct forme

    I am using SECTR STREAM to add additive scene to my game. I have 1 MainScene it has CarManager, and have Additive CarScene which has 40 cars. I need to have reference those cars to my CarManager. I also have MapScene, when I load MapScene I unload CarScene to save memory, if I unload the CarScene those car references to my MainScene will be lost nor not ?

    Regards, :)
     
    Last edited: Dec 16, 2018
  20. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Hello,

    Whenever CarScene is loaded, MainScene gets a notification that it should re-hookup its references. This means whenever MainScene and CarScene are loaded, MainScene will have all of its references to CarScene. When you unload CarScene, MainScene doesn't keep those references as they'll be dead objects (CarScene is removed, therefore all of the cars are removed).

    Please keep in mind that each car must have a unique name or 'path' to be referenced and restored properly.

    Cheers.
     
    MoribitoMT likes this.
  21. MoribitoMT

    MoribitoMT

    Joined:
    Jun 1, 2013
    Posts:
    301
    I see

    In editor mode, if I open MainScene and CarScene together, and get car references from CarScene to MainScene, and In play mode, I unload CarScene and load MapScene, car references in MainScene will be gone, however if I load CarScene back, references will come back in MainScene, right ? If understood correctly. And one las question, is there a any memory or performance cost, because I develop games from low end to high end mobile devices.

    Regards.
     
  22. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    I'm not confused by your use of "from CarScene to MainScene" because the reference (if I understand correctly) should go the other way. The variable for CarManager lives in MainScene and the Cars are in CarScene? So it should be from MainScene to CarScene. Essentially it works this way:

    1. Anytime a new scene is loaded, it tries to hook-up its unresolved references to the previously loaded scenes and
    2. Anytime a new scene is loaded, the previously loaded scenes attempt to hook-up unresolved references to the newly loaded scene.
    The performance overhead at runtime is just the search through the hierarchy to the objects. So let's say you have N cross-scene references, the cost is O(N). The time to resolve is quite fast. The memory overhead is negligible, a couple of strings. All of the processing only occur on a scene load, which will dwarf anything the plug-in is doing.
     
    MoribitoMT likes this.
  23. MoribitoMT

    MoribitoMT

    Joined:
    Jun 1, 2013
    Posts:
    301
    Hi, I already purchased the plugin, it think it suits my needs %100.

    To be honest I had a good design with just 1 scene, but because of memory issues on iPhone 5, I had to split game into multiple scenes. My MainScene has all the managers as singleton and each dependent on each other and being set up on start. This is why my CarManager must stay on MainScene. Problem started when I moved cars to new scene ( CarScene ). I had to get car references from CarScene to CarManager which stays in MainScene. Things become mess after this, but this pugin will save me I think..

    Regards.
     
  24. GrumpyBear33

    GrumpyBear33

    Joined:
    Jan 25, 2014
    Posts:
    7
    Hey!

    I've been trying to make Lightmaps work with a multi-scene setup.

    Everything looked perfect until the build. When I launch a build, the lightmaps are gone (only my dynamic lights are left).
    Is there a way to make this work? Should I bake every scene seperatly before setting them up together.

    There was an earlier post about this, but I,ve gone through all steps (all scene are "additive") and in editor works perfect, but fails in build.

    Any idea ? Thanks!

    EDIT: Something to note: we do change between active scenes from room to room
     
    Last edited: Jan 18, 2019
  25. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Hey GrumpyBear,

    What version of Unity are you using? Have you tried not changing active scenes? Does it fail only when changing active scenes? We have a game released now where we do a lightmap bake on 2018.2. The active scene along with other code-centric scenes are disabled during bake, leaving only static and dynamic geometry to bake. You can inspect the results by opening each scene up individually and inspecting the lightmap settings in each scene individually (don't save, obviously).

    The additive scenes should use Unity's lightmap "merging" (for lack of better term) to ensure the lightmaps load in correctly. I'm wondering if switching the active scene messes with this, as the lightmap is probably merged into the active scene. Can you give that a shot and let me know? We're about to update our game, and I'll try to keep an eye on the lightmaps.
     
  26. GrumpyBear33

    GrumpyBear33

    Joined:
    Jan 25, 2014
    Posts:
    7
    Hey! Thanks for the reply! We are using 2018.30f2.

    We were switching the active scene when the player entered a new room checkpoint, and coincidentally when the level loaded, the player was already inside the first checkpoint. So we were basically switching the active scene right away.

    I moved the checkpoint and it seems to have fixed it. Changing active scenes AFTER the fact doesn't seem to break anything.

    I also did a weird thing where all my scenes are now in a prefab (I'm testing some things for quicker reloading), so that might be what made it work...

    I'll try to update this post with more info as I go.
     
  27. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Hey GrumpyBear,

    Probably the best use of this plug-in is to do the cross-scene referencing which probably won't work with your prefab approach. The cross-scene referencer explicitly looks for references that would be lost across scenes, rather than references that would be lost due to prefabs. Keep that in mind. If you have more info / issues, please either make another post or at the very least send me a message. I only log onto these forums when I get notified ;). Cheers.
     
  28. GrumpyBear33

    GrumpyBear33

    Joined:
    Jan 25, 2014
    Posts:
    7
    Hey! Yes you are right about cross-scene references not being compatible with the prefab thing. I'm just investigating ways to reload (much) faster, and I thought it might have impacted lightmaps.

    After further testing, (I unpacked the prefabs, rebaked the lightmaps and put the checkpoints like before), it seems lightmaps just work now? Now I'm just confused. but it works. So I guess case closed? Maybe doing prefabs then unpacking kept some data for some reason, I don't know. I'll have to do further testing on another level later. But for now it's good. Thanks for your help!
     
    Jodon likes this.
  29. Zeevex

    Zeevex

    Joined:
    Jan 15, 2018
    Posts:
    28
    helloo, i have this asset and i think i'm doing something wrong though, i set the scene as 'Don't load' but at runtime the scene is still active on the scene as i think additive

    i play the game in MainScene with a Character scene for player, scene 1 and background as additive, but i'd like scene 2 to be inactive until i load it in using a script
    upload_2019-2-4_21-54-39.png


    EDIT: I noticed on hover tags that it renders in edit mode, so i built and it wasn't loaded! allgood :D

    Made a script to unload/load in Async transitions work seamless :)
     
    Last edited: Feb 5, 2019
  30. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Glad you found it. There's two settings: The one you're looking at which determines what happens at runtime, and then the Editor has its own "hidden" settings (which is the current state of your scenes when you hit play). I don't override the Editor state in this case which is why they were appearing. Sounds like you figured that out ;).

    Cheers.
     
  31. Zeevex

    Zeevex

    Joined:
    Jan 15, 2018
    Posts:
    28
    Hey Jodon!, this is probably a bit complex but i'm trying to save/load scenes using another asset easy save..
    I notice the unities SceneManager doesn't have a way to reference active additive scenes only the SceneManager.GetActiveScene(which is the MainScene I run to get all the scenes)

    I'm trying to find a way to reference the additive scenes so i can save and load it in when needed.. do you know if theres a work around, or a way i can perhaps reference the active additive scenes through AMS?

    kind regards,
     
  32. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Hey Zeevex,

    I'm a bit confused at what you're trying to achieve. Keep in mind that SceneAssets are not easily referenced in Unity, they have to be loaded by name or index in the SceneManager. So the best you can do is to save the name, like I do in AMS. You can look at AmsMultiSceneSetup.SceneEntry to see how I deal with it in AMS.
     
  33. mattis89

    mattis89

    Joined:
    Jan 10, 2017
    Posts:
    1,151
    Hello! I have the Resource File Limit issue .. But splitting my scene to many would fix that because its like 4gb / scene limit... But I was wondering if this plugin can handle Vegetation Studio Pro? Wich is a gameobject with advanced scripts and gpu based instances? and If I can also put my terrain there in the new scene wich have CTS and other scripts?
     
  34. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Where is the file limit becoming an issue? In the Editor or at runtime? My plugin is only useful if you're able to load at least two of the scenes into memory at once so that you can perform the cross scene references.

    I have not tried that plugin, but in general if it conforms to standard use of GameObjects/MonoBehaviours it should work. There may be an issue where you have to delay the startup actions of some scripts (from Awake or OnEnable to Start) in order to give AMS some time to resolve the cross scene references.
     
  35. mattis89

    mattis89

    Joined:
    Jan 10, 2017
    Posts:
    1,151
    The build dont work if the resource file is over 4gb.. but I would split the scene into many...I would load most of them with async and maby bake the one with terrain and Vegetation Studio on (?)

    Theres only one main scene containing everything...

    Could you do a test for me? Fill a scene to the max so it breaks the 4gb limit.. and then split and build it?
     
  36. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    I'm curious if you're using a 32 bit build as opposed to a 64 bit build? You should be able to test this yourself by breaking up the scene and doing a SceneManager.LoadSceneAdditive. The value of AMS is ease of use and being able to reference objects across scenes which won't be needed for that test.
     
  37. mattis89

    mattis89

    Joined:
    Jan 10, 2017
    Posts:
    1,151
    Im using x86_64 the standard value when building to pc... yea I havent bought ams yet.. But I think it work anyway actually, cant see why it wouldnt, resource folder is the key right :D
     
  38. Bubsavvy

    Bubsavvy

    Joined:
    Sep 18, 2017
    Posts:
    48
    Hey @Jodon,

    Currently I believe our team is running into a race condition. We have a QuestRoutine that is used for swapping between scenes and before unloading the previous scene we are assuming that the references are resolved after using WaitUntil(()=> asynLoadLevel.isDone). The problem is that I think our code is assuming that the references are resolved by this time. Is there some sort of hook or something provided by your tool that can do something like WaitUntil(()=> AmsSceneReferences.SceneReferencesResolved(targetScene))? Also I noticed you had event handlers statically available for OnStart and OnAwake, but im not sure we can use them as there is no guarantee that our delagate would be the last in the Invokation list. Thoughts?
     
  39. Bubsavvy

    Bubsavvy

    Joined:
    Sep 18, 2017
    Posts:
    48
    On another note. You should totally open source this project in a private github repository. :) I would personally like to be able to add change requests and possibly commit some changes of my own with your approval. This of course would be later on down the line for me as we still need to focus on our immediate game. It would also be a good issue tracker for your personal use. Your tool is bomb! ;) Honestly don't get why this is not something that comes shipped with unity by default.
     
  40. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Hey Bubsavvy,

    Have you tried registering for the AmsMultiSceneSetup.OnStart and using that to let your Coroutine continue for one more yield? Keep in mind when 'Scene A' is getting loaded, it will try to resolve the cross-scene references that are 'from Scene A', but any of those could be referencing 'Scene B' which is not yet loaded. So thinking through this, I think you should register for OnStart, load all your scenes, wait until you've received an OnStart for all of them, then yield return null once more to get to the next frame.

    Cheers.
     
  41. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Thanks! I'll keep that in mind. Git has been a thorn in my side for all Unity-related work, but maybe I'll give it another shot since this is code-only. Probably looking at a late-April date to try something like that, but I'm always willing to hear feature requests on here.
     
  42. Bubsavvy

    Bubsavvy

    Joined:
    Sep 18, 2017
    Posts:
    48
    Hey @Jodon,

    As it turns out this was not the issue at all. :( All references are resolved by the time the scene is loaded. I tried the following though and I am not sure if its a bug or what, but even after unsubscribing the delagate that previously existed. OnDestroy and OnStart are triggered multiple times on my separate QuestSceneSwapRoutines.

    Code (CSharp):
    1.     public bool sceneReferencesResolved;
    2.  
    3.     private void Awake()
    4.     {
    5.         AmsMultiSceneSetup.OnStart -= AmsCrossSceneLoadHandler;
    6.         AmsMultiSceneSetup.OnDestroyed -= AmsCrossSceneUnloadHandler;
    7.         AmsMultiSceneSetup.OnStart += AmsCrossSceneLoadHandler;
    8.         AmsMultiSceneSetup.OnDestroyed += AmsCrossSceneUnloadHandler;
    9.     }
    10.  
    11.     private void AmsCrossSceneLoadHandler(AmsMultiSceneSetup sceneSetup)
    12.     {
    13.         if (sceneSetup.gameObject.scene.name == targetScene.name)
    14.             sceneReferencesResolved = true;
    15.     }
    16.     private void AmsCrossSceneUnloadHandler(AmsMultiSceneSetup sceneSetup)
    17.     {
    18.         if (sceneSetup.gameObject.scene.name == targetScene.name)
    19.             sceneReferencesResolved = false;
    20.  
    21.     }
    22.  
    23.     IEnumerator routineDelay()
    24.     {
    25.  
    26.         yield return new WaitUntil(() => asyncLoadLevel.isDone && sceneReferencesResolved);
    27.         yield return new WaitForEndOfFrame();
    28.         gameController.environmentController.DepopulateLocationWithNPCS(previousScene);
    29.         gameController.environmentController.PopulateLocationWithNPCS(targetScene);
    30.         gameController.questController.gameController.SaveNPClocationInScene(previousScene);
    31.  
    32.     }
    Even so. I found the issue. Here is the scenario:
    • NPCSceneSwapRoutine makes NPC internally member of scene they have moved to.
    • NPCSceneSwapRoutine gives a reference to the door in the current scene which contains a "CrossSceneReference" to the interior door which exists in the scene the NPC transitioned to.
    • Player proceed to enter a scene unrelated to the scene the NPC walked into.
    • ISSUE : NPC reference to door in scene where once both the player and NPC existed is now gone!
    I believe the best solution is to be able to add and remove references in scenes on the fly. Does something like this exists?

    Edit : FYI all routines, quests, npc's, system level stuff, etc. are stored in our GameMaster scene which is always loaded.

    Thanks In Advance,
    Troll House Games
     
    Last edited: Feb 14, 2019
  43. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Sort of, we don't have access to it at runtime (but of course you can make your own function to expose it). Look at AmsCrossSceneReferences._mergedScenes. Basically you want to add an entry to that array whenever you're about to move your player over. If the entry is in _mergedScenes before the source of an xRef tries to resolve, it will know to redirect to the new scene if it fails to find it in its target scene. Alternatively, you can use a similar system. A multi-dictionary/set is probably a better structure in this case since I'm worried you'll have duplicate keys (i.e. a level could have been 'merged-to' many possible levels).

    Cheers.
     
  44. Bubsavvy

    Bubsavvy

    Joined:
    Sep 18, 2017
    Posts:
    48
    Will this do. I don't really care if the reference gets removed when the game is stopped at the moment. Was going to just later on create a queue for all of the in-game references to be restored on load. The trouble is too how does one build out a RuntimeCrossSceneReference exactly i'm not sure how this process is done. All i have right now is "targetDoor" which is of type DoorController. My reasoning behind not caring is because GameMaster is never unloaded. All scenes we load are loaded one at a time and removed upon leaving the scene. I'm assuming all i would have to do is populate the RuntimeCrossSceneReference somehow with the instance of the DoorController I have which will remain in memory on the !AmsMultisceneSetup object in the reference list. Your plugin should handle loading up scene references as normal correct?

    Edit : At the moment _mergedScenes has private access. I am honestly not really sure what this is either. Is this some sort of global holder of references from all scenes?

    Code (CSharp):
    1. AmsCrossSceneReferences.GetSceneSingleton(targetDoor.targetScene.scene, false).AddReference(RuntimeCrossSceneReference);
     
  45. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Yes, _mergedScenes is private right now, you would have to add a function to modify it. I think it's pretty safe to say this functionality doesn't exist out of the box. _mergedScenes is a list of scenes that were merged via baking, but can be hijacked for this purpose. If you follow the code closely, eventually you'll see that the cross-scene references try to look-up the object in the expected scene, and if it fails it checks for the merged scenes.

    RuntimeCrossSceneReference is more of something I create internally. It contains the Object, field info, and target info. You probably don't wanna do this at runtime -- the name Runtime refers to the fact that you can resolve it at runtime. You don't wanna create these yourself, they're very cumbersome to get right (hence the need for the plug-in). But you might be able to expose the one you want somehow, then change the RuntimeCrossSceneReference.toScene to the desired one.
     
  46. Bubsavvy

    Bubsavvy

    Joined:
    Sep 18, 2017
    Posts:
    48
    Yeah i don't think we would have that issue with the _mergedScenes. We bake both NavMesh and scene lighting as per scene without having two scenes opened additively. So I have a working fix. The cross scene reference works perfectly though. Exactly for what i needed. I ended up exposing ToRuntimeSerializableField to handle your unique setup for RuntimeCrossSceneReferences. The code is the following :

    Code (CSharp):
    1.  
    2.  
    3. // This works! :D
    4.  
    5. SerializedObject fromObject = new SerializedObject(targetNPC);
    6. SerializedProperty fromProp = fromObject.FindProperty(nameof(targetNPC.transitionDoor));
    7. RuntimeCrossSceneReference reference = new RuntimeCrossSceneReference(targetNPC, TrollHouseSolutions.ToRuntimeSerializableField(fromProp), new UniqueObject(targetDoor), null);
    8. AmsCrossSceneReferences.GetSceneSingleton(SceneManager.GetSceneByName("GameMaster"), false).AddReference(reference);
    9.  
    10.  
    11. // Recommend something like this for Adding??
    12. public void AddHotReference(Scene toScene, Object fromObject, Object fromProp, Object toObject){
    13.     SerializedObject serialObject = new SerializedObject(fromObject);
    14.     SerializedProperty serialProp = serialObject.FindProperty(nameof(fromProp));
    15.     RuntimeCrossSceneReference reference = new RuntimeCrossSceneReference(fromObject, TrollHouseSolutions.ToRuntimeSerializableField(serialProp), new UniqueObject(toObject), null);
    16.     AmsCrossSceneReferences.GetSceneSingleton(SceneManager.GetSceneByName(toScene.name), false).AddReference(reference);
    17. }
    18.  
    19. // This will likely not work since we are calling new. Maybe instead of List<RuntimeCrossSceneReference> use Dictionary<ReferenceUniqueId, RuntimeCrossSceneReference>????
    20. public void RemoveHotReference(Scene toScene, Object fromObject, Object fromProp, Object toObject){
    21.     SerializedObject serialObject = new SerializedObject(fromObject);
    22.     SerializedProperty serialProp = serialObject.FindProperty(nameof(fromProp));
    23.     RuntimeCrossSceneReference reference = new RuntimeCrossSceneReference(fromObject, TrollHouseSolutions.ToRuntimeSerializableField(serialProp), new UniqueObject(toObject), null);
    24.     AmsCrossSceneReferences.GetSceneSingleton(SceneManager.GetSceneByName(toScene.name), false).RemoveReference(reference);
    25. }
    26.  
    27.  
    Edit : Now that I look at this again a dictionary won't work unless you update an internal one base off of the List, because you need it available in the editor to see. Tell me what you think though. I upgraded C# version to be compatible with C# 6 for nameof()
     
  47. Bubsavvy

    Bubsavvy

    Joined:
    Sep 18, 2017
    Posts:
    48
    Hot Reference Proof of Concept

    It doesn't look like much and I know you may want to go about it a different way possibly, but it solves our use case. :) If you let me know what your email is or have a medium I can send you the updated code. Essentially the way I got the persistence to work after leaving the scene was by storing RuntimeReferences in a dictionary where the key is fromObject.GetInstanceId().ToString() + toObject.GetInstanceId().ToString(). I also have to queue this unique id to later on remove stale ones and replace the key with an updated version using the newly instantiated toObject. I do this so that we can remove the hot reference later on. Let me know what you think! :D

    Note : Apparently gifcat didn't do the full upload. I'll add a link to the full one in an edit to this post later.

    Edit :
     
    Last edited: Feb 16, 2019
  48. Jodon

    Jodon

    Joined:
    Sep 12, 2010
    Posts:
    434
    Hey Bubsavvy,

    Sorry I got swamped with work and forgot to get back to you. I'm not sure I understand the use case completely. The SerializedProperties only work in the Editor. My email should be in the documentation. If you can send me a small repro case I'll come up with something.
     
  49. Bubsavvy

    Bubsavvy

    Joined:
    Sep 18, 2017
    Posts:
    48
    Check out the video. I'll send you my edits to your code.
     
  50. keeponshading

    keeponshading

    Joined:
    Sep 6, 2018
    Posts:
    937
    Hi. Is your Advanced MultiScene working together with Unity Adressables?

    I would like to use your cross scene referencing in such an setup.

    main scene loads addititive

    scene01 is adressable
    scene02 is adressable