Improve AssetsManager to keep track of download progress as it is possible with SceneLoader

Hello there,

On the application that I currently working, I found myself refactoring the code that loads assets (mainly .obj files) from SceneLoader to AssetsManager, because of an annoying bug that happens with React 18 and StrictMode (only development environment).

Even though AssetsManager uses SceneLoader internally, the bug doesn’t happen when using AssetsManager.load(). However, using AssetsManager, I cannot keep track of the download progress of the assets, because the following call does not use the onProgress callback (MeshAssetTask.run()):

/**
     * Execute the current task
     * @param scene defines the scene where you want your assets to be loaded
     * @param onSuccess is a callback called when the task is successfully executed
     * @param onError is a callback called if an error occurs
     */
    public override runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
        SceneLoader.ImportMesh(
            this.meshesNames,
            this.rootUrl,
            this.sceneFilename,
            scene,
            (meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[], transformNodes: TransformNode[]) => {
                this.loadedMeshes = meshes;
                this.loadedTransformNodes = transformNodes;
                this.loadedParticleSystems = particleSystems;
                this.loadedSkeletons = skeletons;
                this.loadedAnimationGroups = animationGroups;
                onSuccess();
            },
            null, // <-- here is where it should be passed
            (scene, message, exception) => {
                onError(message, exception);
            },
            this.extension
        );
    }

Later on, I found that the “bug” that was happening to me is that the loadingUI must be explicit hide after the mesh loading is finished (this is not necessary outside the StrictMode). Thus, moving to AssetsManager isn’t necessary anymore.

However, it would be nice to rely on a more robust implementation (AssetsManager) and also use the underlying features that SceneLoader provides.

Personally I opt-out of using React’s <StrictMode>. Does it work for you if it’s wrapped around your React UI rather than the whole app? I also like to initiate core asset/scene dependencies before rendering <App /> but not ideal if you want async loading behaviour.

I wouldn’t try to hack React’s double-rendering with refs/effects but you could put a function in to see if in dev environment, check if rendered the second time then trigger the call… not ideal but at least a temporary development env solution.

Hopefully someone can look into this but I believe it’s besides the point of how you’re setting-up the React environment with BJS.

I have the StrictMode wrapped around the root component. Thus, the entire application runs with it enabled. Before, I had indeed opt-out the StrictMode. What I found out is that most of the bug that happened to me was the because of the loadingUI component that was hanging because of “unmount simulation” form React. With that said, the issue with React is solved on my side.

The context here is more a reference of what happened and the differences between using AssetsManager and directly SceneLoader.

Furthermore, my willing here is on enabling AssetsManager to fully use SceneLoader (when it is used, of course), and Feature proposals/request on GitHub are only allowed with a previous discussion here on the forum. As it approved (in benefit of the BabylonJS), I can create the pull request with the feature.

This the first thing I always remove :rofl: if my babylon.js code (engine init/scene creation/asset loading) is inside a React component.

1 Like