Recognize instance of Babylon entity

Hi everyone! I’m working on reducing the final bundle size of an application built with Reactylon.

Currently, a significant amount of code is being included in the consumer’s final bundle because Reactylon uses instanceof operator to identify the incoming Babylon.js entities and determine how to handle them. For example:

import { Material } from '@babylonjs/core/Materials/material';
import { BaseTexture } from '@babylonjs/core/Materials/Textures/baseTexture';
import { Light } from '@babylonjs/core/Lights/light';

// instance is the Babylon.js entity that i'm dealing with
if (instance instanceof Material) {
   // do something relative on Material (e.g. deal with Material or SubMaterial children)               
} else if (instance instanceof BaseTexture) {
  // do something relative on Texture (attach it on parent Material)
ì} else if (instance instanceof Light) {
  // do something relative to Light
}
// and so on...

This method leverages inheritance and works well in terms of structure. However there’s a downside: it forces me (as a consumer of the library) to indirectly import classes into the final bundle that i may never use. For instance, even if my code doesn’t use any textures, the BaseTexture class still ends up in the final bundle.

To make this more efficient, i’m exploring alternative ways to determine which Babylon.js entity i’m dealing with and i have come up with a few ideas:

  1. Using the class name (or attaching a Symbol in case of missing name due to mangling in production).
  2. Checking for specific properties or methods (duck typing) or relying on some internal Babylon.js markers (e.g., _isMesh).

However, I’m unsure about the robustness of these solutions. Do you have any other approaches in mind or is this a trade-off i simply have to accept?

Internally we rely on getClassName(). That should do the trick :slight_smile:

2 Likes

Valuable info. Thank thank you!

1 Like

If i want to preserve the power of inheritance, what would be the best way to group common entities by type?

With instanceof, i can determine if an entity is a camera like this:

const freeCamera = new FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);
console.log(camera.getClassName()); // FreeCamera

const arcRotateCamera = new ArcRotateCamera('camera2', 0,0,0, BABYLON.Vector3.Zero());
console.log(arcRotateCamera.getClassName()); // ArcRotateCamera

console.log(freeCamera instanceof Camera) // true
console.log(arcRotateCamera instanceof Camera) // true

Now, if i want to achieve the same result without using instanceof, the only approach that comes to mind is something like this:

const cameras = ['FreeCamera', 'ArcRotateCamera', ...];

if (cameras.includes(arcRotateCamera.getClassName())){
   // i'm working with a camera
}

However, this approach is hard-coded, which comes with its own set of issues:

  • Manual maintenance: every time a new camera type is introduced, it must be manually added to the list.
  • Less flexible: it lacks the dynamic nature of instanceof, making it harder to work with extended or custom classes.

Would you suggest a more scalable alternative?

yeah inheritance sucks in that case :frowning: Either checking for “Camera” for instance or “Mesh”

1 Like

I raise with getPrototypeOf in conjunction with getClassName! Ready to face the most aggressive mangling :mechanical_arm: :smile:

  function getBaseClasses(instance) {
        const names = [];
        let parent = Object.getPrototypeOf(instance);
        while (parent) {
            if (parent.getClassName) {
                names.push(parent.getClassName());
            }
            parent = Object.getPrototypeOf(parent);
        }
        return names;
    }