Create instances from glb assets

Hi,

How should I create instances of my .glb assets? I see in docs, that’s done with Mesh.createInstance(), but I’m loading my assets with:


const result: ISceneLoaderAsyncResult = await SceneLoader.ImportMeshAsync("stuff")

But that gives me result.meshes which is AbstractMesh[]. And AbstactMesh is missing the createInstance() method. So I’m quite confused here. SceneLoader.ImportMesh() is depracated - says docs.

So I’m not sure what to do. Also my assets are animated, so I want to make sure the animations will work (instanced as well).

It works but it is not too pretty: Babylon.js Playground


I think the problem is here:

This is the class hierarchy according to the Babylon docs. ISceneLoaderAsyncResult.loadedMeshes can contain InstancedMeshes, too. So they went 1 level up the hierarchy.

Hm… I also found there’s [AbstractMesh.instantiateHierarchy()] (Babylon.js docs)

Which seems to be doing the same thing… I’m testing it now… But then it looks like that each instance is driven by the same animation. So it means that all characters have the same animation…

To have different animations one needs to use clones.

@Jozef_Plata
This is how I’m loading meshes in my game:

        const totalMeshes = characters.length + npc.length + monsters.length + /*items.length + others.length*/ + interactiveItems.length;
        let loadedMeshes = 0

        const addContainers = async (models: string[], pathPrefix: string) => {
            for (let i = 0; i < models.length; i++) {
                this.engine.loadingUIText = `Loading assets [${(loadedMeshes * 100 / totalMeshes).toFixed(1)} %]... Please wait!`;
                const modelGLB = `${models[i]}.glb`
                const container = await SceneLoader.LoadAssetContainerAsync(pathPrefix, modelGLB, this.scene)
                this.assetContainerHolder.set(models[i], container)
                loadedMeshes++
            }
        }

        await addContainers(characters, './characters/')
        await addContainers(npc, './npc/')
        await addContainers(monsters, './monsters/')
        await addContainers(interactiveItems, './items/interactive/')

and then:

entry = this.meshAssetContainerProvider.getAssetContaner(model).instantiateModelsToScene(name => name)
const root = entry.rootNodes[0] as Mesh
const clonedAnimationGroups = entry.animationGroups

3 Likes

@Maiu Thanks, using the containers is the way to do it!

const container = await SceneLoader.LoadAssetContainerAsync("", url, scene, () => {}, ".glb")
        for (let i = 0; i < 100; i++) {
            const instance = container.instantiateModelsToScene()
            const anim = instance.animationGroups[Math.floor(Math.random() * instance.animationGroups.length)]
            anim.play(true)

            const root = instance.rootNodes[0] as Mesh
            const row = Math.floor(i / 10)
            const col = i % 10
            root.position.set(col - 5, 0, -row)
        }

2 Likes