Errors on Scene change when assets aren't preloaded

Hi there,

I’ve been working on a solution to keep our app’s memory footprint down, and this has led me to implementing scenes and scene switching to only keep needed assets on screen at a time.

Along with this is the need to not have every asset in our project preload, but rather only have the necessary assets for the current scene to be loaded.

From what I understand when we call loadSceneHierarchy this will load a new scene in along with the necessary assets for it, and I can see this happening by monitoring the load event of the AssetRegistry. When I load a new scene and all of my assets are set to preload, everything works as expected. Our problem happens when we do the scene switch code and our assets are not set to preload. Scene switching code below:

// Destroy the hierarchy for the current scene
    oldHierarchy.destroy();
    
    self.app.scenes.loadSceneHierarchy(scene.url, function (err, parent) {
        if (!err) {

            self.app.scenes.loadSceneSettings(scene.url, function (err) {
                if (!err) {
                    callback();
                } else {
                    console.error( err );
                }
            });
        } else {
            console.error( err );
        }
    });

I can see the assets are indeed loading as they should, though in the console there are many errors that crop up as noted in the images below. Any insight into these errors would be greatly appreciated.

I’ll also note that these error pop up as the remaining assets are still loading for the scene, so it’s almost as if the engine is trying to act on assets before everything for the scene is actually loaded.

Loading a scene does not wait for assets to load before creating the entities. There’s no connection between the assets and the scene.

I recommend loading the assets first and when they have finished, then loading the scene.

You may need to have a loading screen of some sort to cover destroying the current scene, unloading unneeded assets, loading the new assets, loading the next scene.

Here’s a project example of loading a group of assets at runtime. https://developer.playcanvas.com/en/tutorials/load-assets-with-a-progress-bar/

Awesome, thanks for this!

That info about loading assets first is just what I need I’m pretty sure. Will test it out and report back here.

Ok so loading the assets first has definitely put me along the right path though I’m still encountering a couple strange pieces of behaviour, it seems as though cubemaps might be treated slightly different in terms of the asset pipeline? I’m not sure though so would love some more insight on this!

You can see the errors being thrown now in the screenshots below.

Are you able to reproduce this in a separate project that we could look at?

I’ll see if I can set something smaller up to be reproducible.

I think one of the issues I’m running into is that the way the first scene loads from the Launcher is a little different than the way it has to load when I switch between scenes.

I’m also noticing a difference with how scenes/cubemaps are loaded from the launcher vs. loadSceneHierarchy/assetregistry.

When a cubemap loads from the launcher it adds a single asset by the name of cubemapName_part_0 which is of the type texture

But when I load from the asset registry it seems like I need to load each face of the cubemap as an individual texture. The reason I say this is because if I don’t call load manually on the those textures, when loadSceneHierarchy gets called, they (the six sides of the cubemap) get loaded from it.

I’ve just tried a simple project that loads the cubemap assets before loading the scene and it seems fine? https://playcanvas.com/project/765267/overview/cubemap-loading

Thanks for that, your example is exactly what I expect should happen. I’ve also managed to fork our project and slim it down greatly to just two scenes with some functionality stripped out of them here:

https://playcanvas.com/editor/scene/1091233

If you press “E” from the Home scene it will switch you to the second scene, and if you press “H” from the second scene it will switch you back to the Home scene.

I’ve kept all my logs in there for you to see what I’m seeing, and the issues that are cropping up.

Thanks again!

Sorry, there’s a lot of code and assets there to unpack that makes it difficult to track what is going on.

I’m a bit confused on why the load event is being listened for the whole registry rather than for the specific assets that are being loaded specifically for the seen.

Yea it’s hard to dilute the project down to more than what’s there.

I could change it to listen to only the assets we’ve tagged, but the issue there seems to be that more things that what we tag are actually getting loaded for a scene.

And to me the strangest part is on the initial load of the scene from the launcher you can see the texture cubemapName_part_0 ( Cubemap_Snow_part_0 for our project specifically ) gets loaded but we don’t have any textures in our asset directory that go by that name, so this is throwing off my tracking of assets.

The other reason I was listening for everything to load was because I need to wait until everything is fully loaded in the scene before I tell my other scripts to proceed with what they need to do.

And also that I don’t have control over how assets are loaded when the launcher starts up, as it seems to trigger the scene load automatically.

I’ve simplified the logic right down here so I can track what is going on much easier: https://playcanvas.com/project/765282/overview/load-test-for-thinking-box

Ignoring all the initial loading from the first scene, it turns out that a cubemap asset may not have a resource so I’m also checking if it’s been loaded before requesting an asset load.

Also, the error you were getting was from unloading an asset (the cubemap?) that was being used in the current scene. So I’ve checked against that before unloading it.

The order is now:

  • User presses key
  • Load newScene assets
  • Wait for asset load
  • Load new scene
  • Destroy old scene
  • Unload assets

This was done in a rush so there may be issues here and there but it should get you going at least in the right direction.

Amazing, this is really appreciated! I won’t be able to digest it for a little bit but I will report back with some good news hopefully.

Ok good news, all I had to do was make sure to call .off('ready') on each of the assets to make the scene switching work more than one time in succession.

I do have a couple more questions though. My VRAM still seems to creep up on every scene load, to the point where after about 10 switches, the app will crash on mobile devices still.

Does asset.unload remove all references to assets or is there more work to be done in that regard?

Hi @tb_dev,

asset.unload() will indeed free up any memory allocated by that resource, and from my experience it works as expected.

What VRAM subcategories keep pilling up? There are some things that the engine is controlling like shadowmaps but normally you shouldn’t worry about that.

Changing scenes is an entity hierarchy change, so normally if you exercise absolute control of your assets loading/unloading list that should be enough.

Yea ok that’s what I had assumed should be happening, though this is what I get when I switch from the initial scene to the new scene and then back again to the initial scene. In theory the VRAM should stay consistent if everything is being unloaded properly I would assume.

Initial Scene First Load:
Screen Shot 2021-02-15 at 1.24.54 PM

Initial scene after loading out and then loading back in:
Screen Shot 2021-02-15 at 1.25.25 PM

It seems textures other is increasing a lot, are you by any chance loading and applying scene settings as well? Thinking it may be a skybox being referenced in the scene rendering settings.

Also index and vertex buffers are increasing, that’s an indication of model assets not getting unloaded. Are you using static batching by any chance? That would also increase those two buffers.

Yep you’re right, both of those things are happening. We’re calling app.scenes.loadSceneSettings after loadSceneHierarchy and we are also using static batching on things in these scenes (which I actually have other questions about)

Do we need to have batching disabled for these scenes then? And also is calling loadSceneSettings not necessary?