Loading a new scene in Android

Hi everyone,

I’m currently exploring the Babylon Native library on Android and have run into a tricky issue that I haven’t been able to solve.

My app allows users to select from a list of .glb files and view them in a separate Activity using BabylonView. The first time I launch the Activity, everything works fine — the selected model is loaded and rendered correctly.

The problem comes when I exit the Activity and select a different .glb. When the Activity restarts, it still shows the previous scene, even though I’m updating the path and attempting to load a new file.

I’ve tried cleaning things up in onStop() and onDestroy() using:

scene.dispose();
engine.dispose();

To load the .glb file I use a slightly modified version of the experience.js that is available in the Android’s project in github: BabylonNative/Apps/Playground/Scripts/experience.js at master · BabylonJS/BabylonNative · GitHub
My modifications (around line 47):

let path = typeof globalThis.modelPath !== "undefined" 
    ? globalThis.modelPath 
    : "app:///Scenes/brie_comte_robert.glb";

BABYLON.SceneLoader.AppendAsync(path).then(function () {
    BABYLON.Tools.Log("PlaygroundActivity BJS, Loaded");

And here’s how my Activity loads the script:

    override fun onViewReady() {
        loadScene()
    }

    fun loadScene() {
        Log.i("BabylonNative", "load: $modelPath")
        isSceneInitialized = true

        val injectedJs = "globalThis.modelPath = '$modelPath';"
        val sourceUrl = "runtime-injected.js"

        mView.eval(injectedJs, sourceUrl)
        mView.loadScript("app:///Scripts/experience_variant.js")
    }

Thank you all for reading, and a big thanks to the Babylon team for all the impressive work!

EDIT: I’ve tried with and without the scene.dispose()and engine.dispose().

Just a few thoughts.
You append a new scene to an engine that just destroyed the original scene, maybe the append gets confused? Why not loadAsync the new scene.

The loader you use is deprecated and the replacement is a much better loader. (Check the documentation for it)

Does your mView.loadscript fires the second time? Maybe a caching thing.

Hope one of these help you out.

cc @BabylonNative

A simple test I would do:

  • console.log(path) in the AppendAsync promise, to be sure variables are properly set function is called
  • add scene.dispose() before AppendAsync
  • do not load if path is empty and try with an empty path after using a non empty path
1 Like

Hello Niels, thank you for your answer! :slight_smile:

I’ve tried with and without the scene.dispose() and engine.dispose functions.
Without calling those, the previously loaded scene stills play, but if I dispose of the engine and/or the scene, nothing happens (I just have a black screen or the previous scene that’s frozen).
The mView.loadscript() function is called the second time (the Android logs show that this part of the code runs as expected), but the JS code isn’t executed (the JS logs don’t appear the second time).

Concerning the deprecated function,
I should then replace BABYLON.SceneLoader.AppendAsync(path) by BABYLON.AppendSceneAsync("path/to/model", scene);. Is it the ‘module level function’ to use as recommended here: https://doc.babylonjs.com/typedoc/classes/BABYLON.SceneLoader ?

Hello Cedric, thanks for the advices!

The logs show that the path are as expected, and I still have a default file path in case it is not the case.
I’ve tried adding the scene.dispose() before the AppendAsync, but, I still end up with the same result, it seems that once I’ve left the Activity, the mView.loadScript() method don’t work anymore.

Can you do a repro with BN playground example?

Hello,
Sorry for the late response, it took me some time to prepare an isolated test project.
I can update it if necessary.

Here’s the repository: https://github.com/HalTobin/BabylonNativeTest
The project shows what happens when exiting the PlaygroundActivity and opening it again.

I was away for a few days. I’ll take a look shortly

I get this error the 2nd time I try to load a .glb. It might explain the behavior you see.

2025-04-22 10:44:42.725 15244-15244 PlaygroundActivity      com...neaufactory.babylonnativetest  I  load: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Avocado/glTF/Avocado.gltf
2025-04-22 10:44:42.727 15244-15290 BabylonNative           com...neaufactory.babylonnativetest  E  [Uncaught Error] SyntaxError: Identifier 'wireframe' has already been declared

I have the same error as well. Probably related to the fact that these are const defined in the loaded script.
I can see 2 solutions:

  • clear the JS runtime when exiting the Activity
  • modifying the js script with a function for loading a scene, calling this function instead of the loadScriptmethod everytime

Is there a way to clear the JS runtime, since this would match my use case better? (I wouldn’t want the JS runtime to still be running when the user has left this part of the app)
I’m currently investigating the library to see if I’ve missed something.

I think it’s possible to shutdown the engine and restart from scratch. Babylon.js scripts will have to be reloaded and parsed again. So there will be latency and not necessary I think as it’s possible to clear the scene and load a new one. You should try to fix the wireframe issue before trying another solution. I think you are close to a working app.

I didn’t find how to shutdown the engine and restart it from scratch, I’ve encountered the Wrapper.finishEngine() method, but then I’m not able to start it anymore.

I’d rather process this way because the 3D viewer is only a tiny and mandatory part of my application, so I’d prefer to clear the engine once used, the latency for restarting it isn’t a problem in my use-case.

I’m also still investigating how to make the app work without clearing the engine, but this wouldn’t be an ideal solution.

after finishEngine is called, the engine will be created when Wrapper.surfaceCreated(holder.getSurface(), this.getContext()); is called. check public void surfaceCreated(SurfaceHolder holder). So, simply recreate a view. Anything in the logcat?

Hi @HalTobin any progress?

Hello,
Sorry for the lack of updates.
I unfortunately didn’t succeed with BabylonNative and tried other libraries.