The 6 scenes in the test project auto-switch after 3 seconds. Observe that the total texture memory in VRAM (PlayCanvas Profiler) don’t get released properly.
You can enable the PlayCanvas Profile by hovering the “Play” Button and check “Profiler”.
@moka I have seen you are already working on the Ammo memory leaks, maybe this one is related?
I think what is happening is normal given the existing scene loader.
loadSceneHierarchy(): Load a scene file, create and initialize the Entity hierarchy and add the hierarchy to the application root Entity.
So basically this isn’t a scene switcher, but mainly loads a scene (entities and assets dumped in VRAM) and appends it to the existing scene as a child entity. This method won’t unload anything.
You will have to manually take care of unloading all scene assets, much like you destroy the oldHierarchy.
You are doing everything fine, but still you will need to manually unload all assets that get loaded by each scene. This is by design, and there are some cases that it can be useful (fast scene switching, assets with small VRAM footprint etc).
oldHierarchy.destroy();
That method will remove only the scene entities from the scene hierarchy, it will not unload the resources used (models, materials, textures etc.).
You could post a feature request in the engine repo about that, for a method that can handle the scene assets unloading.
thanks for the answer. In the sample project, how should one tackle this? The asset registry “this.app.assets” has all the assets listed. Even textures where I set “preload” to false have their loaded flag set to true. So how can I find out which assets are currently loaded, so I can unload them on scene change?
Good point, textures that have preload to false on run-time eventually they will get loaded automatically as soon as they get used somewhere. For example an entity referencing a model that references materials that reference that texture.
I think since you are changing scenes, what you expect is to unload all assets currently loaded. So you could iterate through all the assets in the asset registry, check the loaded property and if it is set to true, do myAsset.unload().
If you do this as a blocking step, after you destroy the oldHierarchy and before loading the new scene, I think that would work nicely.
To iterate through all assets in the registry you can use either the filter method (without doing anything meaningful on return) or the this.app.assets._assets private property (it’s an array with all registry assets). Example code:
EDIT: I’ve just found out that the material was still set to preload true (which also loads the texture where preload is set to false). I’m currently investigating it further
Yes, exactly, anything that references the textures will trigger the action to load them. Unticking preload in those materials will keep both the materials and textures from getting loaded:
Yes, whatever asset has been removed from VRAM using the unload() method, it has to be reloaded manually using the load() method available in the registry.
@Leonidas So the developer has to manually store a list of all assets per scene for the occasion when he wants to load that scene again? This seems quite counter-intuitive - since the scene already knows all if its assets to load (e.g. when loading it the first time).
You make a fair point, there have been a lot of requests for improving the scene changing methods in Playcanvas. I’d say go ahead and post this as a feature request in the engine repository.
Regarding assets loading/unloading, speaking from my experience, as soon as you get up to speed with how everything works that fine grained control pays off in the long term. Not only between scenes but inside a single more complex scene helps keep performance and memory usage in control.