Can't dispose of cloned and impostorized meshes

Hi there !

So I have an annoying one, because I haven’t yet been able to reproduce a playground, I’m stuck because the scene.onAfterStepObservable listener doesn’t seem to be listening.

So my real issue is as follows :
I want to create a dice rolling app. So I clone the original dice a certain amount of time, set physicsImpostors and once they finished rolling I want to get rid of them. And basically the getting rid thing doesn’t work, the dispose() throws this error :

image

But I can’t reproduce my issue yet (although the playground is all set) because the part where I watch the moment the mesh stops moving is not called. Sorry to ask, but it seems I need help even for showing my actual problem… does somebody have a clue ?

The playground is here.
I’ll try to provide a simple description of what it contains :

  • I set up the basic scene environment, with enabled Physics (using deterministic cannon engine)
  • In importOriginal() I import the mesh and store it as the “original”
  • In instantiate(), I create a certain amount of clones, and give them a physical body. I then try to listen to the moment they immobilize (but the listener doesn’t work as demonstrated by line 83). When they all do, I want to dispose of all the meshes. The current playground doesn’t show it yet, but on my project that’s when the above error is thrown.
  • impostorize() is called in instantiate(), this is where the instance is given the PhysicsImpostor needed for collisions.

[ EDIT 10 Aug ]
A Pull Request solving this problem has been accepted. The fix should be available next week
[ / EDIT ]

You need to create the engine with deterministicLockstep=true (see lines 1-3):

https://playground.babylonjs.com/#66PS52#126

1 Like

Thank you ! I missed that part.

But now I got a problem… My playground doesn’t reproduce my issue, once they all immobilized the meshes get disposed() just as expected, which is what I want but not what I have on my local project.

I’ll look further into it and try to set up a playground that throws the same error I have. I guess the mere log I showed above doesn’t hint at anything ?

The error you pasted shows that remove is not a function of world. You should check that your CannonJSPlugin.world property is ok and not overriden at some point.

In the constructor, it is created as this.world = new this.BJSCANNON.World();.

Thanks for the suggestion, I’ll check that out asap !

So… it turns out it’s a little bigger than I thought.
I looked into the world property as you suggested and found this
:

It seems the prototype doesn’t have an remove() method indeed (but removeBody() instead). So I figured it must be an issue about cannon. And doing my research, I realized :

  • I am actually using cannon-es instead of cannon. That is why my issue wasn’t reproduced on the playground.
  • Cannon-es has had several threads regarding this kind of problems, some of them discussing an awkwardly similar issue, that has been brought up here on babylon’s forum.

A Babylon PR has since fixed this issue (in 5.0.0-alpha.16), following this issue here.

But while the deprecated add() method was replaced with addBody(), the remove() method is still used and I assume that it is what’s throwing the error (the parallel seems obvious).

Since I can’t reproduce the problem on the playground due to cannon-es being used instead of cannon, here is a stand alone html file that demonstrates the issue :

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>cannon.js + babylon.js - basic integration example</title>
  <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
  <style>
    body {
      margin: 0;
      padding: 0;
    }

    canvas {
      width: 100vw;
      height: 100vh;
    }

    #scene-explorer-host,
    #inspector-host {
      position: absolute !important;
    }
  </style>
</head>

<body>
  <canvas id="renderCanvas"></canvas>
<!-- replace below CDN with 5.0.0-alpha.15 version and you'll see the fixed issue about deprecated world.add()-->
  <script src="https://unpkg.com/babylonjs@5.0.0-alpha.16/babylon.js"></script>
  <script type="module">
    import * as CANNON from 'https://unpkg.com/cannon-es@0.17.0/dist/cannon-es.js'

    // Canvas
    const canvas = document.querySelector('#renderCanvas')

    // Engine
    const engine = new BABYLON.Engine(canvas, true)
    window.addEventListener('resize', () => engine.resize())

    // Scene
    const scene = new BABYLON.Scene(engine)

    // Camera
    const camera = new BABYLON.ArcRotateCamera(
      'camera',
      -Math.PI / 2,
      Math.PI / 2.5,
      15,
      new BABYLON.Vector3(0, 0, 0),
      scene
    )
    camera.attachControl(canvas, true)

    // Light
    const light = new BABYLON.HemisphericLight('light', new BABYLON.Vector3(0, 1, 0), scene)

    // Box
    const box = BABYLON.MeshBuilder.CreateBox('box', {}, scene)

    // Physics
    window.CANNON = CANNON // force the usage of cannon-es
    const physEngine = new BABYLON.CannonJSPlugin(false)
    scene.enablePhysics(undefined, physEngine)

    // Ground
    const ground = BABYLON.Mesh.CreateGround('ground1', 10, 10, 2, scene)
    ground.physicsImpostor = new BABYLON.PhysicsImpostor(
      ground,
      BABYLON.PhysicsImpostor.BoxImpostor,
      { mass: 0, friction: 0.5, restitution: 0.7 },
      scene
    )
    ground.position.y -= 2

    // Box body
    box.physicsImpostor = new BABYLON.PhysicsImpostor(box, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 5 }, scene)
    box.physicsImpostor.setAngularVelocity(new BABYLON.Quaternion(0, 10, 0, 0))
    box.physicsImpostor._physicsBody.angularDamping = 0.5

    scene.debugLayer.show()
    engine.runRenderLoop(() => {
      scene.render()
    })
    setTimeout(() => {
      /** ---------------------------------------------
        * BELOW IS THE BREAKING LINE
        */
      box.dispose()
    }, 3000)
  </script>
</body>

</html>

I’d like to submit a PR about this based on the merge that fixed the add() part, but not before confirming my conclusion was right. Sorry to bother, hope I made it clear enough to evaluate. :smiley:

1 Like

That’s very clear, thanks! However, I don’t know physic engines, so I will let @RaananW or @Cedric answer this one.

Hey! thanks for the analysis :slight_smile:

So you are saying that you want to change remove to removeBody? if it is available in the old cannon implementation - be my guest! If it isn’t, you can check if the function exists and run the right one. In both cases - a PR will be very appreciated :slight_smile:

1 Like

I forgot the “what’s new” notes in the PR so I immediately closed it, I hope it doesn’t matter !

The PR is now available here
The method falls back to old cannon’s implementation in case (just like the fix for world.addBody() does)

1 Like

merged, thank you very much!

Sure, I’m really new to this stuff but I’ll enjoy contributing wherever I can in the future. :slight_smile:
Will the fix be available in the upcoming 5.0.0-alpha.38 ?

Yes it will be. not sure when alpha 38 will be released. This week for sure.

1 Like