Skip to content

Prefabs

A prefab is a reusable entity template stored as a .esprefab file. You create prefabs from existing entities in the editor, then instantiate copies anywhere in your scene. Each instance can override individual properties while staying linked to the source prefab.

Editor Workflow

Creating a Prefab

  1. Set up an entity (or entity tree) in the hierarchy
  2. Right-click the root entity → PrefabSave as Prefab…
  3. Choose a save location in the content browser

Alternatively, drag an entity from the hierarchy into a content browser folder.

The entity and its children become a prefab instance — linked to the saved .esprefab file.

Instantiating a Prefab

Drag a .esprefab file from the content browser into the hierarchy panel. A new instance is created with all the original entities and components.

Editing a Prefab

Double-click a .esprefab file in the content browser to enter prefab edit mode. The editor loads the prefab as a temporary scene where you can modify entities directly. Changes are saved back to the .esprefab file when you exit, and all instances in the current scene are automatically synced with the updated prefab.

Overrides

When you modify a property on a prefab instance, it becomes an override. Overridden properties are visually marked in the inspector.

  • Apply to Prefab — writes instance overrides back to the .esprefab file and updates all other instances
  • Revert Prefab — discards all overrides, restoring the instance to match the source prefab
  • Unpack Prefab — removes the prefab link, turning the instance into regular entities

Access these via right-click → Prefab on a prefab root entity.

Runtime API

Use the Prefabs resource to load and instantiate prefabs inside a system. It handles asset loading and entity creation in a single call.

import { addStartupSystem, defineSystem, Res, Prefabs } from 'esengine';
addStartupSystem(defineSystem(
[Res(Prefabs)],
async (prefabs) => {
// Accepts file paths or addressable addresses
const { root, entities } = await prefabs.instantiate('prefabs/Enemy.esprefab');
}
));

Options

OptionTypeDescription
baseUrlstringBase URL for resolving asset paths
parentEntityParent entity to attach the prefab root to
overridesPrefabOverride[]Property overrides to apply on instantiation

Applying Overrides

Pass overrides to customize instances at spawn time:

const { root } = await prefabs.instantiate('prefabs/Enemy.esprefab', {
parent: parentEntity,
overrides: [
{
prefabEntityId: 1,
type: 'property',
componentType: 'Transform',
propertyName: 'position',
value: { x: 200, y: 100, z: 0 },
},
],
});

PrefabOverride

FieldTypeDescription
prefabEntityIdnumberTarget entity ID within the prefab
typestring'property' | 'component_added' | 'component_removed' | 'name' | 'visibility'
componentTypestringComponent to modify (for property and component_removed)
propertyNamestringProperty name (for property)
valueunknownNew value (for property, name, visibility)
componentDataobjectComponent type and data (for component_added)

InstantiatePrefabResult

FieldTypeDescription
rootEntityThe root entity of the instantiated prefab
entitiesMap<number, Entity>Mapping from prefab entity IDs to world entities

Nested Prefabs

Prefabs can contain references to other prefabs. The high-level prefabs.instantiate() API handles nested prefabs automatically — all referenced prefabs are recursively loaded and flattened into a single entity tree. For advanced use cases, the low-level instantiatePrefab() function is available:

import { instantiatePrefab } from 'esengine';
const result = await instantiatePrefab(world, prefab, {
assetServer: assets,
assetBaseUrl: 'https://cdn.example.com/game',
parent: parentEntity,
overrides: [
{ prefabEntityId: 1, type: 'property', componentType: 'Transform', propertyName: 'position', value: { x: 100, y: 50, z: 0 } },
],
});
OptionTypeDescription
assetServerAssetServerAsset server for loading referenced assets
assetBaseUrlstringBase URL for resolving asset paths
parentEntityParent entity to attach the prefab root to
overridesPrefabOverride[]Property overrides applied during instantiation

Next Steps