How to dispose everything?

Hi folks!

I have an application which consists in one main menu with several options. One of the options redirects to the 3D scene. The first time I enter the scene everything works as expected. But if I go back to the main menu and I enter again I face some problems:

  • If I dispose the scene before I go back to the main menu, when I try to enter again, I get this error:
Uncaught TypeError: Cannot read properties of null (reading 'globalPosition')

At some point the activeCamera is null.

  • If I don’t dispose it before going back to the main menu, when I enter again I get tons of warnings like this one:
WebGL: INVALID_OPERATION: bindBufferBase: object does not belong to this context.

So my question would be, how can I dispose everything so every time I enter the application from the main menu everything is started from scratch? Like when I hit F5 to refresh the entire page.
I can’t create a playground to reproduce the problem as the application is huge, containing tons of meshes, materials, etc.

Many thanks in advance!

Hi saci,

Without knowing what’s in your scene or where that error came from, it’s very difficult to speak with certainty about what will solve it. Generally speaking, any resource you make “on the scene” (cameras, common textures, etc.) will be disposed when the scene is disposed, but that won’t dispose resources the scene doesn’t know about nor will it invalidate references being held by other objects. If that error you mentioned is coming from within Babylon.js code itself, please let us know what the call stack is because it might be a bug. However, if the call stack has non-Babylon code in it, then it’s likely something that isn’t part of Babylon (and so isn’t automatically equipped to be disposed when the scene disposes) is holding onto references it shouldn’t, ending up in a state where it tries to request things from objects that have already been disposed.

More generally, if you have objects that you want to be disposed at the same time the scene is disposed, you can have them hook themselves into the scene’s onDisposeObservable so that they can automatically clean themselves up when the scene is disposed. If all your scene’s objects are hooked into the scene’s disposal in one way or another, then they should all clean themselves up and you should be able to enter from the main menu over and over without causing problems. Hope this helps, and best of luck!

2 Likes

First of all, thank you for your reply. I know that it’s hard to come up with a good response without some context but as the app is so big I can’t set a playground with everything.
This is the call stack:

Uncaught TypeError: Cannot read properties of null (reading 'globalPosition')     zone.js:182 
    at Scene.bindEyePosition (scene.js:971:1)
    at Scene.finalizeSceneUbo (scene.js:991:1)
    at StandardMaterial.Material._afterBind (material.js:828:1)
    at StandardMaterial.PushMaterial._afterBind (pushMaterial.js:65:1)
    at StandardMaterial.bindForSubMesh (standardMaterial.js:1261:1)
    at Mesh.render (mesh.js:1948:1)
    at SubMesh.render (subMesh.js:365:1)
    at Function.RenderingGroup.renderSorted (renderingGroup.js:204:1)
    at RenderingGroup.renderTransparentSorted (renderingGroup.js:170:1)
    at RenderingGroup.render (renderingGroup.js:135:1)

Gotcha, and thank you for sharing the call stack. Unfortunately I think tracking this down is just going to be a debugging journey, and since we can’t see the code itself there’s only so much help we can offer. I’d recommend starting by trying to figure out what Scene is throwing the error.

  • Is it the new Scene that you created after disposing the original one? If so, go to the place in your code where you think the camera should be created and set, and check to see that it’s (1) happening at all and (2) happening at the right time. If it is, something’s unsetting it, and you need to find out what and why; and if it isn’t, that could explain why the active camera is null.
  • Is it the old Scene that was disposed? If so, you probably need to go further up the call stack to try to figure out who’s still trying to render a dead Scene, then terminate whatever flow of logic is causing that to happen before you call dispose().

The steps I described above probably won’t lead you all the way to an answer, but that’s how I would approach debugging further to learn more. Sorry we can’t be more help, but by tracing through the code I hope you’ll be able to resolve it pretty quickly. Best of luck!

2 Likes

Thank you @syntheticmagus for your hints. They have helped me a lot to find the actual problem, which turns out not to be a Babylon related problem but Angular related. In my application, the scene itself is a component and all the logic is in a service. The problem was that the service was provided in the root, so it is not destroyed when the component with the scene is destroyed, therefore, there are still elements that are listening for events from the old scene. By changing that (destroy the service when the component is destroyed) everything works as expected.
Once again, many thanks! I love this community.

2 Likes