Babylon.js Editor: What is the recommended way to create reusable prefabs/chunks?

Hi everyone,

I’m coming from Unity and I’m trying to understand the best way to create reusable objects/prefabs specifically in Babylon.js Editor.

For example, let’s say I want to create a Coin that I can use throughout my game. I would like to create it once and then spawn many instances of it in different levels/scenes.

I also plan to build my game using chunks. Each chunk would be a separate Scene that I can later instantiate/spawn through a Chunk Manager as the player progresses through the game.

From what I understand from the Babylon.js Editor documentation, instantiate seems to work with Scenes. So I’m wondering if the recommended workflow would be something like:

  1. Create the Coin as a separate Scene in Babylon.js Editor.

  2. Create each Chunk as a separate Scene, containing objects such as Coins, enemies, obstacles, etc.

  3. Instantiate the Coin Scene inside the Chunk Scenes.

  4. Then instantiate the Chunk Scenes through my Chunk Manager during the game.

Is this the correct approach in Babylon.js Editor?

One of the reasons I’m considering this workflow is that, if I later replace or modify the Coin model, I would like the changes to be reflected wherever that Coin is used, similar to how a Unity Prefab works.

So, what would be the recommended Babylon.js Editor workflow for creating something equivalent to Unity Prefabs, especially when those prefabs are used inside reusable Chunks that are themselves instantiated by a Chunk Manager?

Thanks!

cc @julien-moreau

I could always use an active user of Nebu2, it already has prefabs and Id be willing to support any feature you would request that is reasonable. All the Known Issues will be addressed here soon. But its stable enough to make some pretty cool scenes with.

Unfortunately prefabs are not yet supported by the Editor :frowning:
Meanwhile you can only create a scene that you’ll be able to instantiate multiple times using the decorator @sceneAsset Babylon.js Editor Documentation but is asks to rely on code way more than using a prefab system. I’m not far from having a cool prefab system but it’s not yet ready and pretty unstable.

Share demos made with Nebu2! @Maxi may be interested!


I have a recreation of the physics playground.


And a couple other demos showing how to attach animations and scripts.

Its pretty cool if you import an 3d asset it scrapes the entire hierarchy and rebuilds it in the NEBU format so the entire structure is rebuilt true to the original model but with all the editing and ECS bindings setup. Including making the correct material and texture prefabs.

Things are still in the early stages but I was able to make a simple first person shooter, the plugin eco system to expand the editor in any way (demonstrated by importing Havok in as a package), tools for building to containers, webpack deployments, or even a single page embedded deployment.

The scripting language is setup like as attachable components just like Unity and you can pass prefabs and other things into the scripts through the UX just like it as well.

Still needs lots of TLC but yeah, a user would be dope who can start filing issues. I can make rapid fixes for you if I know what you need. Most features are not out of reach.

First of all, thanks a lot for all the help so far!

I’m using a corn.scene as a reusable object/prefab. It has a mesh and a script attached to it.

Originally, I tried using:

@nodeFromDescendants("coinHitbox")
private _coinHitbox: Mesh | null = null;

This works correctly when I play corn.scene directly, but when the scene is instantiated through:

@sceneAsset("corn.scene")
private _coin: AdvancedAssetContainer | null = null;

const instance = this._coin.instantiate();

the script is instantiated correctly, but _coinHitbox is null.

I found that I can retrieve the node manually from the instantiated hierarchy instead:

this._coinHitbox =
    this.mesh
        .getChildMeshes(false)
        .find(m => m.name.includes("coinHitbox")) ?? null;

This works correctly for the instantiated scenes.

I also had another issue with collision detection. I was using:

if (this._coinHitbox.intersectsMesh(this._playerHitbox, false)) {
    this._collect();
}

At first, some coins were being collected immediately when they were instantiated.

I eventually realized that the coin was being created at its initial position and then moved to the spawn position. The collision check was running during that very short interval, so it could detect the player before the coin had been moved to its final position.

I fixed this by delaying the collision check until the next update, after the coin had already been positioned.

So everything is working now.

Thanks again for the help!

I just reproduced the problem with @nodeFromDescendants and this is a bug I introduced in the latest release I’m so sorry :frowning:
I’m fixing it with the GUI bug and I’ll let you know.
Meanwhile you can rely on the @visibleAsEntity decorator Babylon.js Editor Documentation to link you node “coinHitbox”. This one still works and power literally my entire game Out 4 Blood Out 4 Blood

For the collisions I think you are right, but the onUpdate method is called after the onStart method and I expect placements to be done before the onUpdate. Maybe I’m wrong by expecting that? It’s because it’s a multiplayer game that you are making?

Thanks again for your feedbacks :heart:

Thanks a lot for taking the time to reproduce the issue and for the detailed explanation! I really appreciate it.

Thanks for confirming that @nodeFromDescendants is a bug in the latest release. In the meantime, @visibleAsEntity works perfectly for me, so I’ll keep using it until the fix is released.

Regarding the collision issue, it’s not a multiplayer game. I’m building the level using reusable chunk scenes. Each chunk has empty TransformNodes that act as spawn points, for example corn_spawn_01, corn_spawn_02, etc.

When the chunk starts, I instantiate the corn.scene for each spawn point and then position the instance like this:

for (const spawn of spawns) {
  const instance = this._coin.instantiate({
      predicate: (entity) => true
  });

  instance.rootNodes.forEach(root => {

      root.parent = this.transform;

      root.position = spawn.position.clone();

      root.position.y = 10;

  });
}

So I think what was happening is that the corn.scene instance was being created first, its onStart() was being called, and then before I had a chance to set root.position, the onUpdate() was already detecting the collision while the coin was still at its initial position.

Thanks again for all your help and for working on the bug!

Thanks for all those info!!
I just fixed the problem with @nodeFromDescendants decorator. I’ll be available in next version soon.
But the fix for the GUI takes more time than what I expected so I’ll not be able to deploy today :frowning: I’m working actively on it and I’ll keep you updated here

Just deployed! v5.5.1