Theme:

Model

Model(key, cache?)Promise<U.Object3D>

Async global function which loads and returns an imported 3D model.

// Load using imported object name
const model = await Model('meaowy.glb')
// Load using an asset key
const keyedModel = await Model('c586e69cc2db0a64c26310...')

world.add(model)

Cache and cloning

Pass true for cache when the asset will be cloned or loaded repeatedly. Always use await object.clone(); cloning can be asynchronous.

const template = await Model('unit.glb', true)
const instance = await template.clone()

Runtime instances

Configure colliders and metadata before adding the clone:

instance.traverse(object => {
	if (!object.geometry) return
	object.collider = false
	object.userData.unit = unit
})

parent.add(instance)

parent.add(instance) synchronizes the child and queues its descendants for rendering; an ordinary model needs no extra parent sync or World registration. Use world.add(instance) for a top-level object, and world.remove(instance) for cleanup. See World when a late-added subtree contains update callbacks or lights.

Raycasting is separate. Register each non-skinned mesh that should receive interactions; groups are ignored:

instance.traverse(object => {
	if (object.isMesh && !object.isSkinnedMesh) {
		world.addRaycastable(object)
	}
})

Bounds and transforms

Imported meshes have a local geometry.boundingBox. Once processed for rendering, each non-skinned mesh also has an engine-maintained boundingBoxWorld; a model root or Group has no aggregate bound. After changing transforms, call sync(). Use Box3.setFromObject() when an aggregate world-space hierarchy bound is needed. The standard raycaster currently skips skinned meshes. See Mesh and Box3.