Search Unity

Make SceneAsset full time citizen asset in the Runtime

Discussion in 'General Discussion' started by katoun, Feb 26, 2019.

  1. katoun

    katoun

    Joined:
    Dec 26, 2012
    Posts:
    91
    Hello,

    I was trying for some time to create a scene-state management system, where I can map a GameState class to a specific SceneAsset. I created a ScriptableObject where I have this mapping data. Then I made a root scene where I have the StateManager and the reference to the mapping data. From this test I found that the Unity's scene management is a bit inflexible:
    - SceneAsset is only available in the UnityEditor API but not in the UnityEngine, even thought it can be serialized as a UnityEngine.Object which is the base of all assets.
    - SceneManager.LoadScene[Async] has only 2 ways to identify a scene asset: by the index in the Build Settings scene list or by the scene name/path. No option to identify a scene by a unique identifier that is not dependent on the scene name, path in the project's folder or any ordering.
    - Any SceneAsset that is not included in the BuildSettings scene list, even thought is it referenced in the main scene like any other asset, does not get included into the build.
    Because these limitations, I had to make some workarounds. Added a script that hooks to the build event from where I had manually injectall the referenced SceneAssets to the Build Settings scenes list and map GameStates to the corresponding scene name/path. Also, on any scene asset change of it's name or path, I had to re-save the ScriptableObject data to map GameStates to the new scene asset's path.

    My suggestion is not to completely change the way current system works. Let the scene list from the build settings work as it is now, but also let SceneAsset be available in the runtime API and also contribute the the build process as all the other assets do. So, if there is a scene in the build settings that inside has a game object with a script that contains a reference to a SceneAsset, that SceneAsset gets added to the BuildSettings scene list at build time (transparent for the user), and can be used with SceneManager.LoadScene[Async] by it's SceneAsset reference. As I know, each asset has an unique identifier at the runtime(after the build process) that is based on the guid (witch is the Editor global identifier of a file) and it's local fileID (to identify multiple assets that can be contained in one file: fbx has skeleton, geometry, animations and materials).

    Regards.
     
  2. Jean-Fabre

    Jean-Fabre

    Joined:
    Sep 6, 2007
    Posts:
    429
  3. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    I actually agree w this. Unexpected since these types of posts are usually dumb.

    Having references to scene assets in unityengine instead of editor would make a bunch of stuff easier.
     
  4. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Yeah, I also think it's pretty weird that we've got a proper object to refer to scenes, but at runtime have to resort to strings or numbers.

    This is the only thing I'm not sure about. I'm not saying I disagree, I'm really not sure either way.

    On one hand, yeah, scenes don't need to be treated differently to any other data. On the other hand, it's quite handy to have one place where we can pick what's included in or excluded from a build. Of course that itself depends on how we implement other things, and there are other solutions which could be more practical anyway...
     
  5. alfish

    alfish

    Joined:
    Apr 5, 2017
    Posts:
    26
    I was able to make it work with this code. I only tested this in 2020.3.6f1, Linux x64, Mono.
    This is the closest to what I'd expect Unity to do if they were to implement it.
    I'm releasing it to public domain (no warranties), so feel free to use it in your projects without attribution.

    https://bitbucket.org/alfish/workspace/snippets/yXr856/referencing-sceneasset-by-guid-at-runtime

    It works by storing the GUID of the SceneAsset in a struct, so you can move, rename and change build indices freely. The property drawer displays it as a Scene object in the editor, so you can drag-drop, etc, as normal.
    A build processor is used to include a pre-loaded asset with all GUID to build-index mappings in the build, so these GUIDs are accessible at runtime.

    The code is in root namespace, but you can easily change it if you want. I suggest using a local or embedded package to include it in your projects.

    Example usage in a MonoBehaviour/ScriptableObject field:

    public SceneReference sceneToLoad;
    var loading = SceneManager.LoadSceneAsync(sceneToLoad.sceneIndex);
     
    theforgot3n1 likes this.
  6. theforgot3n1

    theforgot3n1

    Joined:
    Sep 26, 2018
    Posts:
    205
    Great solution alfish! It's the best I could find googling this. Would it be alright if you could write the code in these forums in case the link dies in the future? I also suggest making a github repo, so us mere mortals can star or fork it to show appreciation. ;)

    Also, I added a constructor

    Code (CSharp):
    1. public SceneReference(Guid sceneGuid)
    2. {
    3.     this.sceneGuid = sceneGuid;
    4. }
    to the SceneReference struct, as it was previously not possible to generate it through code. Might be worth considering adding.
     
  7. alfish

    alfish

    Joined:
    Apr 5, 2017
    Posts:
    26
    EDIT: You might prefer the registry version instead of git url. See my comment below.
    ---
    I've updated the snippet, and also made it into a Unity Package. The code for the pkg is in my git repo here.
    You can add it in Unity Package Manager using this Git URL (should auto-update with the main branch):
    https://bitbucket.org/alfish/com.unity_x.modules.sceneref.git

    Or, you can also download v0.1.0 as a standalone tgz file and add it locally (no updates). I'm also adding a backup in this comment as attachment (.tgz isn't supported in forums directly, so I wrapped it in a .zip).

    Note that the snippet version is in root namespace, but the package version is in UnityEngine namespace and it goes into a separate UnityEngineX.SceneRef.dll. I opted for just leaving it at that namespace, so it feels as close as possible to a native implementation (and I don't really want to use a namespace of my own for this). If Unity ever decides to to use the same name (SceneReference(s)), they'd probably be implementing this feature, so in that case you'd probably want to switch to that anyways. If you don't like this, you can, of course, change it as you prefer, and/or clone or fork the repo, etc. Or just use the snippet version.
     

    Attached Files:

    Last edited: Jul 21, 2021
  8. theforgot3n1

    theforgot3n1

    Joined:
    Sep 26, 2018
    Posts:
    205
    You sir have transcended the realm of gods. Thank you for the convenient Git URL and package :p

    I'm curious, do you expect to make any changes to the functionality in the future?
     
    jeffersonrcgouveia likes this.
  9. alfish

    alfish

    Joined:
    Apr 5, 2017
    Posts:
    26
    As of now, no (I can't think of any related functionality worth implementing anyways), so don't expect updates, unless a Unity update breaks it or something. Major version is zero because I didn't do any extensive testing.

    However, there's a minor issue that is happening in my machine (2020.3.6f1, Linux x64) where the array of preloaded assets sometimes is getting added with null entries on builds. I'm pretty sure it's NOT caused by my code, but I can't be 100% sure with the few tests I did. This looks like a Unity bug. If you guys are not having that happen, but it happens with my code, please let me know, because I can add code to remove all null entries on the post build hook (but I didn't want to "fix" this issue if it has nothing to do with my code).

    Also, note that I did no testing at all with "subscenes" (it seems this is a thing when you install some package related to ECS). I don't even know how that works, so if you're using that, you have to test it on your own to see if it works or not.
     
  10. theforgot3n1

    theforgot3n1

    Joined:
    Sep 26, 2018
    Posts:
    205
    For unrelated reasons, I downgraded to 2019.4 to test something. I noticed that the code in SceneReference.cs and SceneReferenceBuildProcessor.cs use C# features which are unavailable in 2019. The offending pieces of C# features are the following two

    Code (CSharp):
    1. public int sceneIndex => this.sceneGuid switch
    2.         {
    3.             var sceneGuid => Array.FindIndex(UnityEditor.EditorBuildSettings.scenes, s => s.guid.ToString() == sceneGuid)
    4.         };
    5. // Which I changed to
    6. public int sceneIndex
    7.         {
    8.             get
    9.             {
    10.                 var sceneGuid = this.sceneGuid;
    11.                 return Array.FindIndex(UnityEditor.EditorBuildSettings.scenes, s => s.guid.ToString() == sceneGuid);
    12.             }
    13.         }
    14.  
    And


    Code (CSharp):
    1. if (PlayerSettings.GetPreloadedAssets() is {} preloaded) {
    2.       int n = preloaded.Length - 1, i = n;
    3. // Which I changed to
    4. UnityEngine.Object[] preloaded = { };          
    5.     if (PlayerSettings.GetPreloadedAssets() != null) {
    6.       int n = preloaded.Length - 1, i = n;
    7.  
    I am not totally sure my changes are equivalent. However, unless the features cannot be replaced by older C# code, it may be worth considering making it compatible with 2019.
     
  11. alfish

    alfish

    Joined:
    Apr 5, 2017
    Posts:
    26
    Yes it's equivalent. I'll incorporate those changes later and update.
    EDIT: Oops, my bad. I guess I was was half-asleep when I read your post, @theforgot3n1 .
    Actually, only first is equivalent. Second is a non-null check with var definition, so it means:
    Code (CSharp):
    1. var preloaded = PlayerSettings.GetPreloadedAssets(); if (preloaded != null) {
     
    Last edited: Jun 23, 2021
    theforgot3n1 likes this.
  12. alfish

    alfish

    Joined:
    Apr 5, 2017
    Posts:
    26
    I updated the package's git repo. Changelog
    Contrary to what I thought, it doesn't seem like Unity notifies or check updates when using git URLs.
    It seems you'd need to manually re-add the URL for it to update.

    For this reason, I have published it on an open registry so that Unity can actually do updates.
    Installation instructions are here. Once you add the registry, it will appear in the Package Manager window after a refresh.
     

    Attached Files:

  13. MasterSubby

    MasterSubby

    Joined:
    Sep 5, 2012
    Posts:
    252
    You have to manually up the version number in the package JSON file before committing and it will allow you to update without doing that.

    Edit: Read the package.JSON file, looks like you're doing the right thing. Don't believe that's how it's supposed to work.
     
    Last edited: Jun 26, 2021
  14. alfish

    alfish

    Joined:
    Apr 5, 2017
    Posts:
    26
    Yeah, that makes the git URL method almost pointless. It's merely a convenience.
    See: https://docs.unity3d.com/2021.1/Documentation/Manual/upm-ui-update.html
    It should at least notify updates when you click refresh, but it won't even do that. You would have to watch the repo to know of updates, then do it manually.

    So it's better to just use a registry instead.
     
    theforgot3n1 likes this.
  15. a_loupas

    a_loupas

    Joined:
    Mar 17, 2021
    Posts:
    16
    I have installed the package successfully and I have replaced SceneAsset with SceneReference in my scripts. My problem is that I had a Custom inspector with something like this

    panelItem_SO.scene=(SceneAsset)EditorGUILayout.ObjectField("Scene", panelItem_SO.scene, typeof(SceneAsset), true);


    This doesn't work for SceneReference though. I am new to inspector scripting, so do you have any idea how I could make it work ?
     
  16. alfish

    alfish

    Joined:
    Apr 5, 2017
    Posts:
    26
    Firstly, which version are you using? You can check the SceneReferenceDrawer class at v0.1.1 to see how it's handled. The code in v0.1.1 (linked snippet) is a lot simpler than v0.2.0 (latest package version), so you might prefer checking that version to understand editor scripting. The other, v0.2.0, is more complex because I do a trick to display "missing" references properly. In v0.1.x missing refs are displayed the same as "none".

    That said, bear in mind that SceneReference is not a UnityEngine.Object, it's not even a reference type. It's a struct, simply containing the GUID string that POINTS to the SceneAsset Object. So my guess is that you want to do something like:
    EditorGUILayout.PropertyField("Scene", property, ...)

    where property is a SerializedProperty on that scene field (a struct). That method will automatically call the drawer, which knows how to display the struct.
    Otherwise (if you're not using SerializedProperty but accessing the target object directly, which seems to be what you're doing), you'd have to get scene guid field as a string and handle that yourself with AssetDatabase and stuff, like I'm doing in SceneReferenceDrawer (see linked snippet v0.1.1 code). Though the code is not too complex, I recommend the first method instead, if you can use it.

    All of that is, of course, assuming your custom script needs to use SceneReference for runtime code in the first place. Depending on your use case, you could be fine with just using SceneAsset if it's for editor-only code. But I assume that's not your case, obviously.
     
    Last edited: Jul 21, 2021
  17. a_loupas

    a_loupas

    Joined:
    Mar 17, 2021
    Posts:
    16
    I am using the latest version. I do not want to display the struct so the first option doesn't work for me. To be more accurate, I want to call your CustomPropertyDrawer from mine. There must be a way to call it but I cant find it.


    Code (CSharp):
    1. //Field on PanelItem_SO
    2. ...
    3. [HideInInspector]
    4.     public SceneReference scene;
    5. ...
    6. //Code in PanelItem_SO_Editor
    7.  
    8. public override void OnInspectorGUI()
    9.     {
    10.         DrawDefaultInspector();
    11.  
    12.         panelItem_SO.itemType = (panelItemType)EditorGUILayout.EnumPopup("Item Type", panelItem_SO.itemType);
    13.         switch (panelItem_SO.itemType)
    14.         {
    15.             case panelItemType.Scene:
    16.                 {
    17.                    //Display here SceneReference -- Call Your  SceneReferenceDrawer for PanelItem_SO.scene
    18.                     break;
    19.                 }
    20. }
    21. }
    If I use

    Code (CSharp):
    1.  
    2.  case panelItemType.Scene:
    3.                 {
    4.                     SerializedObject so = new SerializedObject(panelItem_SO);
    5.                     SerializedProperty serializedProperty = so.FindProperty("scene");
    6.                     EditorGUILayout.PropertyField(serializedProperty, true);
    7.                     so.ApplyModifiedProperties();
    8.                     break;
    9.                 }
    10.  
    11.  
    Nothing is being draw
     
    Last edited: Jul 22, 2021
  18. alfish

    alfish

    Joined:
    Apr 5, 2017
    Posts:
    26
    No, EditorGUILayout.PropertyField will call the custom property drawer, not the generic struct drawer.
    I believe that's because of HideInInspector. Don't use that attribute if you're custom-drawing the class. I believe that attribute will mark the property as "invisible".

    If I understood correctly what you're trying to do, it seems you want to selectively show a field or not, based on another field's value. So I think you want to do something like this:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. [CustomEditor(typeof(InspectedClass), true)]
    4. public class InspectedClassEditor : UnityEditor.Editor
    5. {
    6.   public override void OnInspectorGUI() {
    7.     // this var will be set when panelItem property is reached; this means that panelItem
    8.     // field must be in InspectedClass BEFORE any other fields which depend on that value
    9.     var itemType = default(PanelItemType);
    10.  
    11.     serializedObject.Update();
    12.     var property = serializedObject.GetIterator();
    13.     if (!property.NextVisible(true)) return;
    14.     // root has children; now at first child property
    15.     do {
    16.       switch (property.propertyPath) {
    17.         // property = child[i]
    18.         case "m_Script": continue; // if you don't want to draw script field
    19.         case nameof(InspectedClass.someField):
    20.           // whenever someField is default drawer, use break (or no case for it)
    21.           // else draw it here and use continue
    22.           drawSomeField();
    23.           continue;
    24.         case nameof(InspectedClass.panelItem):
    25.           // draw and set variable
    26.           itemType = drawPanelItemAndGetValue(); // whatever is your implementation
    27.           continue;
    28.         case nameof(InspectedClass.scene):
    29.           // if selected, use default drawer for SceneReference
    30.           if (itemType == PanelItemType.Scene) break;
    31.           else continue; // else, dont draw anything
    32.         case nameof(InspectedClass.otherType):
    33.           // if selected, use default drawer for that field
    34.           if (itemType == PanelItemType.OtherType) break;
    35.           else continue; // else, dont draw anything
    36.         // case etc: etc
    37.       }
    38.       // use default drawer for any other field
    39.       EditorGUILayout.PropertyField(property, property.isExpanded);
    40.     } while (property.NextVisible(false));
    41.     serializedObject.ApplyModifiedProperties();
    42.   }
    43. }
     
    Last edited: Jul 22, 2021
    a_loupas likes this.
  19. a_loupas

    a_loupas

    Joined:
    Mar 17, 2021
    Posts:
    16
    With some modification it worked perfectly. Thank you very much ! Your code was extremely useful!
     
  20. keola117

    keola117

    Joined:
    Sep 11, 2021
    Posts:
    15
    Bro, my brain is numb. I have no idea how to use your package after downloading it? Is there a namespace or something. I've been trying to build an mmorpg and i have been running into issue after issue with mirror because it cant handle scene changes. so, I built masterscenemanager and loaded the sceneasset and using unity editor cant be used in the application so, i have no way of grabbing my scenesset build on runtime through standalone. I downloaded you package. whats the easiest way to use it? cause again, my brain is literally going numb from all this S*** i've been dealing with, in the past week with issue after issue after issue. lol Make a youtube video. lol
     
  21. keola117

    keola117

    Joined:
    Sep 11, 2021
    Posts:
    15
    btw, this is what I'm trying to build on. My brain is a little less numb now. lol However, now I'm just super stressed unity cant handle something like preserving a scene hierarchy natively after 12 years. hhh


    Still, you should make a youtube video about this, or I will I guess after I figure this out myself. Would save me a lot of time. lol

     
  22. alfish

    alfish

    Joined:
    Apr 5, 2017
    Posts:
    26
    @keola117 To clarify: in my package, you still don't use SceneAsset at runtime, you use SceneReference which works like SceneAsset in the editor.

    From the README file:

    Sorry if this wasn't very clear, the SceneReference class from the repo is in namespace UnityEngine.
    The second line is a field in your ScriptableObject or MonoBehaviour class.
    The last line is the usage for loading a scene at runtime. That's all there is to it. (If you want more advanced info about usage, though, I suggest checking this issue in the repo).

    SceneReference.cs is actually somewhat simple, so if you want, you can probably understand a lot just by looking at the code.

    That said, I agree that it's a good idea to include usage in the wiki, with screenshots and a simple example class that you can download (with example usage in ScriptableObject and MonoBehavior), so I'll add that when I release the next version. Maybe I'll even add a playable example scene for download too, someday, if I have the time.
    I think a video would be an overkill though, but feel free to make one linking to the wiki if you want to.
     
    Last edited: Sep 29, 2021
  23. keola117

    keola117

    Joined:
    Sep 11, 2021
    Posts:
    15
    i cant actually find your cs in my actual unity but, I was looking at documentation, and you can load all scenes in a for int = 1; using a basic string and int struct then select your "active" scene on the end by index/name. thats the route I'm gonna go. seems really simple.


    P.S, yourScenereference shows up as null so, idk. maybe my unity just didnt build your tar correctly.
     
  24. alfish

    alfish

    Joined:
    Apr 5, 2017
    Posts:
    26
    @keola117 Note that when you have the buildIndex of the SceneReference, that's enough to get the other info at runtime using methods like:
    SceneManager.GetSceneByBuildIndex(i) // Scene has properties name, path, etc at runtime
    SceneUtility.GetScenePathByBuildIndex(i)

    Note also that you can use the struct in arrays, for example:
    Code (CSharp):
    1. [CreateAssetMenu]
    2. class MyScenes : ScriptableObject {
    3.   public SceneReference[] gameLevels;
    4.   public List<SceneReference> mapWorlds;
    5.   // then assign in inspector
    6. }
    Also, make sure you're on latest 0.2.1 version, I recommend you use Package Manager method (see wiki) to install from upm-packages.dev so you get any eventual bugfix/feature updates. If you are and think you found a bug you may want to report it in the issues section of the repo (with screenshots).
     
    Last edited: Sep 30, 2021
  25. keola117

    keola117

    Joined:
    Sep 11, 2021
    Posts:
    15
    Code (CSharp):
    1. //script 1
    2.  
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using UnityEngine;
    6. using System;
    7.  
    8.  
    9.  
    10.  
    11.  
    12.  
    13. [Serializable]
    14. public struct AppSceneRef
    15. {
    16.    public string sceneGUID { get { return SceneGUID; } set { SceneGUID = value; } }
    17.    public int sceneIndex { get { return SceneIndex; } set { SceneIndex = value; } }
    18.  
    19. [SerializeField]
    20. private string SceneGUID;
    21.  
    22. [SerializeField]
    23. private int SceneIndex;
    24.  
    25.  
    26.     [SerializeField]
    27.     public AppSceneRef(string mySceneGUID,int mySceneIndex)
    28.     {
    29.         SceneGUID = mySceneGUID;
    30.         SceneIndex = mySceneIndex;
    31.     }
    32.  
    33. }
    34.  
    35.  
    36. //script 2
    37.  
    38.  
    39. using System.Collections;
    40. using System.Collections.Generic;
    41. using UnityEngine;
    42. using UnityEngine.SceneManagement;
    43.  
    44. public class MasterSceneApplicationLauncher : MonoBehaviour
    45. {
    46.  
    47.  
    48.     public List<AppSceneRef> myAppSceneRef = new List<AppSceneRef>();
    49.     // Start is called before the first frame update
    50.  
    51.  
    52.     private void Awake()
    53.     {
    54.         for( int i = 1; i < myAppSceneRef.Count; i++){
    55.            // SceneManager.LoadScene.Add
    56.         }
    57.     }
    58.     void Start()
    59.     {
    60.        
    61.     }
    62.  
    63.     // Update is called once per frame
    64.     void Update()
    65.     {
    66.        
    67.     }
    68. }



    his is the route im going, im going to load the scenes as addative, and after the for loop finishes I'm gonng set scene active by name. login screen. that should make it all match so my server can listen across all scenes in a client version and in editor version before i go a script only build.
     
  26. keola117

    keola117

    Joined:
    Sep 11, 2021
    Posts:
    15
    upload_2021-9-30_15-4-45.png
    i think i messed up with my indexor so I'm amending it his way,

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.SceneManagement;
    5.  
    6. public class MasterSceneApplicationLauncher : MonoBehaviour
    7. {
    8.  
    9.  
    10.     public List<AppSceneRef> myAppSceneRef = new List<AppSceneRef>();
    11.     // Start is called before the first frame update
    12.  
    13.  
    14.     private void Awake()
    15.     {
    16.         for( int i = 0; i < myAppSceneRef.Count; i++){
    17. if(i == 0){
    18. continue;
    19. }
    20. else{
    21.             SceneManager.LoadScene(i, LoadSceneMode.Additive);
    22.         }
    23. }
    24.         SceneManager.SetActiveScene(SceneManager.GetSceneByName("SCOLoginScreen"));
    25.     }
    26.     void Start()
    27.     {
    28.        
    29.     }
    30.  
    31.     // Update is called once per frame
    32.     void Update()
    33.     {
    34.        
    35.     }
    36. }

    However, thats still just building the game via index, when the game get bigger i need to still build it via the struct and have the name declaration matter. know anyway I could fit that into the for loop or in awake? cause. this game will have 3 mps per planet, and will have region maps for the asteroid belts etc, + generated galaxy maps eventually. so, index is gonna be hard to keep track of eventually if i build this way.
     
  27. keola117

    keola117

    Joined:
    Sep 11, 2021
    Posts:
    15
    @alfish now, I'm getting this issue WITH the updated code and scenemane typo correction,




    any idea?? maybe, move the set active to the void start(){}?


    EDIT: that did the trick!
     
    Last edited: Sep 30, 2021
  28. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,860
    Not to poke my head into someone else's conversation I somewhat skimmed over, but doesn't addressables somewhat already do what you're trying to do with this 'SceneReference' fix being discussed here?
     
  29. keola117

    keola117

    Joined:
    Sep 11, 2021
    Posts:
    15
    I tried using addressables and it wasnt building my scenes correctly. this is working what I'm doing. only issue is now, my login is getting stuck in an infinite loop i am debugging it and as far as i can tell, im logging in, I find the scene I'm in, and the scene I'm looking for returns true but, I never go to it. (remind you this work when i run in editor but, not in application)

    Code (CSharp):
    1.  if (ClientLoginToken.TokenSuccess) {
    2.  
    3.             LoginNotificationTxt.text = "Login Success!" + "\n \n Loading you into world..";
    4.             Scene myScene = SceneManager.GetActiveScene();
    5.             LoginNotificationTxt.text = "Login Success!" + "\n \n Loading you into world.." + "\n Moving from "+ myScene.name;
    6.             SCOLoadTicket mySCOticket = PlayerPanel.GetComponent<SCOLoadTicket>();
    7.             mySCOticket.SetNewLoadTicket(PlayersEngine.transform, myScene, SceneManager.GetSceneByName("PlanetarySelection"));
    8.             SceneManager.MoveGameObjectToScene(PlayersEngine, SceneManager.GetSceneByName("SCOLoadScreen"));
    9.             SceneManager.SetActiveScene(SceneManager.GetSceneByName("SCOLoadScreen"));
    10.         }
     
  30. keola117

    keola117

    Joined:
    Sep 11, 2021
    Posts:
    15
    if your curious why, I'm doing so much runback it's because eventually some of my sandbox levels will be generated at 400-500MB probably (wormhole function like in eve-online) and i need to migrate to a loadscreen always and eventually put a byte reader and loading bar UI. Also, the loadscreen is the index 1. and the developer build doesnt return an error so, i have no idea why the application is getting stuck in a loop. really wish editor build and application builds worked the same. save me a lot of freaking time.
     
  31. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,980
    Yes, it does. Not sure why OP is doing this, but if addressables are not building correctly the right course of action is to try and resolve that, rather than this weird hacky alternative.
     
  32. theforgot3n1

    theforgot3n1

    Joined:
    Sep 26, 2018
    Posts:
    205
    Do addressables allow you to put SceneAssets (or an equivalent) directly into fields in scripts? If so, that would definitely be an alternative. I highly suspect it does not work that way though. Not sure what part of this solution is weird either.
     
  33. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,860
    That's not exactly how addressables work. You put an asset into your addressables groups, and then you can select that addressable's address in an 'AssetReference' or similar field.

    For example, my current UI addressable scenes:
    upload_2021-9-30_23-16-48.png

    And I encapsulate my addressable scenes what I call a 'scene data object' scriptable object (not the best name), which has an AssetReference field, where I can select a scene, and the object handles the scene loading, unloading, and keeping track of whether its loaded or unloaded:
    upload_2021-9-30_23-18-30.png

    The 'Scene Asset Reference' is what's referencing the scenes in my addressables. So I don't have to fart ass around with build indexes or build orders. I just use these SO's and reference them where I need to load and unload scenes.

    I suggest reading up and doing some tutorials on addressables.
     
    neginfinity and MadeFromPolygons like this.
  34. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,980
    Basically, what @spiney199 said :D
     
  35. theforgot3n1

    theforgot3n1

    Joined:
    Sep 26, 2018
    Posts:
    205
    Addressables genuinely look like they would be useful in organizing references and keeping things tidy. However, for someone who just wants SceneAssets to behave like any other UnityObject that can be referenced in scenes at runtime, switching their setup to use addressables is going to be great deal more work than adding a few scripts to turn your scenes into regular objects.

    Is that the right long-term solution? Perhaps not. Depends on the scale of the project, if it's dependent on other asset management systems, etc.

    My point is, especially to someone who isn't too experienced with Unity, when you say "it's basically like Addressables" they might think you're saying it's an equivalent level of work and also a small, self-contained solution when it isn't.
     
  36. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,860
    Well the bottom line is Unity, by default, doesn't support using scene assets in the inspector. Addressables aren't that much of a change up to your workflow either, honestly. They're just a wrapper on top of the already existing asset bundles system, but just a number of magnitudes easier to use.

    I'm not exactly experienced, either. Only started writing my first lines of code/using Unity in February this year, and I knocked together that scene data object in an afternoon earlier this month. I could post the code if you like.

    Nonetheless I was just putting it out there as a suggestion, and something I still recommend that you look at.
     
    MadeFromPolygons likes this.
  37. minsley

    minsley

    Joined:
    Sep 25, 2015
    Posts:
    3
    Thanks for the tip on Addressables. Turns out they handle this case pretty well (Unity has a tutorial for it now).

    This let me take a list of .unity scene files, assigned via inspector, and load/unload them at runtime like so:

    Code (CSharp):
    1. List<AddressableAssets.AssetReference> Scenes;
    2. Scenes[0].LoadSceneAsync(LoadSceneMode.Additive);
    3. Scenes[0].UnloadScene();
    They also have nice async support, returning an AsyncOpHandle, which itself has a .Task for regular async await.

    https://learn.unity.com/tutorial/addressables-scene-loading#
     
    smartplay and DragonCoder like this.
  38. starikcetin

    starikcetin

    Joined:
    Dec 7, 2017
    Posts:
    340
    I was the maintainer of JohannesMP's solution mentioned in this thread. That project is now archived. I have written a new library from scratch for this purpose:

    https://github.com/starikcetin/Eflatun.SceneReference

    Give it a go and don't hesitate to open issues if you experience any problems.
     
    Hexalted likes this.