Loading and Unloading Scenes Properly (Flax Question)

The related forum topics I could find here but not asking the same question on a broader sense. I am at this point in Flax where the framework coding needs this feature. I have not really gone through testing this with the small amount of info in these two posts. I/We could use some clarity on this subject.

@mafiesto4 Any proper advice here is immensely appreciated. Please make it so a toddler can understand…I am talking about me. :rofl:

TLDR: None on this one. Have to read the details. There are also details from doing this same thing in different engines and experience during runtime. I give examples that work very well in Unity that are adapting to Flax easily with some small differences. Flax has a lot more options.

Flax Manual Refs (what I could find on this):
Class SceneReference | Flax Documentation (flaxengine.com)
Class Level | Flax Documentation (flaxengine.com)

[Why Level.LoadScene{…] and Level.UnloadScene[…] takes different scene class type? - Scripting - Flax Forum (flaxengine.com)](Why Level.LoadScene{...] and Level.UnloadScene[...] takes different scene class type?)

Multiple scenes - General - Flax Forum (flaxengine.com)

Design Concept Explanation:

  • Usually there is some sort of ‘Data Scene’ that is the first loaded scene then all other scenes that are loaded will gather ‘Coordination Data’ that all scenes will use.

  • In the Aurora Engine by Bioware (and Electron and Eclipse) it has what is called a Module (object ie oMod or oModule) that is loaded and handles all the ‘Game Mode’ settings and variables. You can set/get new variables on this that are very handy in coordinating things that when loading something that does not exist yet can load in and be ready to go.

This is where I started. Bioware designed their engine incredibly well. Especially once I started trying to reverse engineer their scripting and other systems for Unity/CS. Took awhile but I came to the conclusion Bioware had some seriously skilled and forward thinkers with their engine design.

  • UE4/5 does this but in a very strange way with how to configure the ‘Game Mode’ and use the built in UE Save System. It was very difficult to get to work properly but does work. The other option is to use ini files and save files to prepare scenes being loaded then if needing to unload them process them through a saving system and cached ini if this scene will be loaded again later. It is design decision and one reason why UE4 open world type games have had lots of strange bugs that many companies simply don’t fix or maybe they don’t know how to solve the issues. Once I solved the ‘oModule’ in UE4 it made loading scenes with proper coordination stupid fast and reliable. I am stunned how well it works to be honest. Since it is a very strange method requiring a few steps to get it working it is error prone though from the design side. Good document workflow must be adhered to. Works great though.

  • Unity has this feature built in but not well advertised on how to do this properly. Here is the code on how to do this properly. This script is placed in the start up scene, kept in memory always, then the actual scene that game play is in (via start location/scene or saved location). This method is very simple once know and works reliably. Every so often there is some sort of memory glitch that causes some issue. Usually when Unity is being hammered with scene stuff. A data save system must be used here and validated every so often to keep this reliable. I use a .NET based database system I created and is extremely fast (txt files with/without encryption). So, no need for SQL or other type databases to do this.

Note: I have other things in my CacheObjects function but removed them for clarity.

    void CacheObjects()
    {
        //Module Object and Time        
        oModule = gIO_Objects.GetModule();
        if (oModule != null)
        {
            gModule = oModule.GetComponent<gModule>();
            gTime = oModule.GetComponent<gTime>();
        }

        else if (oModule == null && bLoadModuleOnce == false)
        {
            SceneManager.LoadSceneAsync("_Module", LoadSceneMode.Additive);
            bLoadModuleOnce = true;
        }
    }

Questions for Loading and Finding:

  • Loading ‘The Module’ scene on Start as the first scene then keeping it open forever while in run mode.
  • Scenes in Flax are treated as Actors with Transforms. Are they treated the same as any Actor with script components?
  • Flax does these loads in the background. Is there a bool check we can do or maybe a % variable we can monitor while the scene is being loaded? This would make sure we can configure the scene after it is loaded. In the case of The Module it will load fast but we still need to make sure it is fully loaded into memory prior to doing something with it.

Is this all there is to it? The Flax manual is not descript/clear on this.

SceneReference  MyScene;

Level.LoadSceneAsync(MyScene);
  • Set/Get data and variables to this ‘MyScene’? Is it similar to this? Obviously this is Unity code but Flax is very similar. I just want to make sure to do this the Flax Way the 1st Time.
//Game Object References
GameObject oModule;
public gModule gModule;

//Module Object and Time
if (oModule == null)
{
     oModule = GameObject.Find("oModule");
     if (oModule != null)
     {
         gModule = oModule.GetComponent<gModule>();
     }
}

Note: gIO_Time is part of the framework namespace holding all Time functions. Added below for clarity.
nDayOfWeek = gIO_Time.GetDayOfWeek(oModule);

// The Current Day of Week
public static int GetDayOfWeek (GameObject oModule)
{
      int nVal = 1;
      int nDayCurrent = GetDay(oModule);
      int nDaysPerWeek = GetDaysPerWeek(oModule);
      int nWeekCurrent = GetWeekofMonth(oModule);

       nVal = nDayCurrent - ((nWeekCurrent - 1) * nDaysPerWeek);

       //Underrun in Array Protection
       if (nVal < 1)
       {
           nVal = 1;
       }

       return nVal;
}

Questions for Unloading Properly:

  • Is it enough in Flax to simply call the function(s) below and check the bool state?
  • Can/Should we use this bool as a decision maker to execute our scene database of variables (Flax has some options on this too…see below) then execute one of the (which one is best?) unload functions to remove the scene from memory?

  • Saving Scene Data. What is included in the save data? Is it like the Bethesda style of saves where every Actor/Object and papyrus scripts and basically everything is included in the ESS file. This design is convenient but has all sorts of drawbacks. It works in the Bethesda style of design but I much prefer the Bioware and UE4 style of clean scenes (originals) then configure as needed based upon some save data.
  • How do we bool check for the save function is complete then execute the unload function after?

Cheers
Olander

The reason of SceneReference is that Scene Asset has the same ID as Scene object - for proper sync but it leads to problems in C# where we would have two objects of the same ID. So Guid or SceneReference is the best way to use for scene loading handling. We should add more utilities for this to make coding easier.

Regarding, load/unload functions the best is to use the ones with Async in the name as those start to load the scene asset in a background without blocking the game and perform the load later on.

Thanks. Appreciated. Mostly understood. Toddler here. :rofl:

So if we declare and keep track of the GUID of Actor(s) (including scenes) we are guaranteed to find this efficiently and store this variable as a reference in memory? Then control (Load/Save/Unload) as needed?

What about the bool check as to when it is loaded/saved or not?

Best method to Find the scene and keep it as a reference? I like a few of these but I want to make sure I am using the right options. More than 1 is perfectly fine since Bioware also had some nifty options to get objects with ease. Unity and UE4 (had to use an expanding collision sphere…ugly) are more brute force. Flax has A LOT of options. :grinning_face_with_smiling_eyes: Love it.

Currently I am using FindActor(Type,String) for everything but this is only using a current scene and not something more global. Then checking the GUID to see what object it really is then check the script data.