Flecs: Prefabs
Description: A fast entity component system (ECS) for C & C++

| Flecs v4.1 A fast entity component system (ECS) for C & C++

Loading...
Searching...
No Matches
Prefabs

# Introduction

Prefabs are entities that can be used as templates for other entities. They can provide a convenient API for creating assets natively in the ECS. Prefabs have the following features:

- Prefab components can be shared across instances
- Inherited components can be overridden on a per-instance basis
- Inherited components can be auto-overridden on a per-prefab basis
- Prefab inheritance makes creating variations easy
- Prefabs can have children that are instantiated for instances
- Prefab children can be easily identified with prefab slots
- Prefabs are runtime accessible and modifiable
- Prefabs can be mapped to types for easy access in the C++ API
- Natively supported by Flecs Script & the JSON serializer

The following example shows how to instantiate a simple prefab:

- C

  ECS_COMPONENT(ecs, Defense);
  // Create a SpaceShip prefab with a Defense component.
  ecs_entity_t SpaceShip = ecs_entity(ecs, {
  .name = "SpaceShip",
  .add = ecs_ids( EcsPrefab )
  });
  ecs_set(ecs, SpaceShip, Defense, {50});
  // Create two prefab instances
  ecs_entity_t inst_1 = ecs_new_w_pair(world, EcsIsA, SpaceShip);
  ecs_entity_t inst_2 = ecs_new_w_pair(world, EcsIsA, SpaceShip);
  // Get instantiated component
  const Defense *d = ecs_get(world, inst_1, Defense);
  EcsIsA
  const ecs_entity_t EcsIsA
  Used to express inheritance relationships.
  EcsPrefab
  const ecs_entity_t EcsPrefab
  Tag added to prefab entities.
  ecs_entity_t
  ecs_id_t ecs_entity_t
  An entity identifier.
  Definition flecs.h:361
  ecs_entity
  #define ecs_entity(world,...)
  Shorthand for creating an entity with ecs_entity_init().
  Definition flecs_c.h:235
  ECS_COMPONENT
  #define ECS_COMPONENT(world, id)
  Declare & define a component.
  Definition flecs_c.h:145
  ecs_ids
  #define ecs_ids(...)
  Convenience macro for creating compound literal id array.
  Definition flecs_c.h:699

- C++

  struct Defense {
  float value;
  };
  // Create a SpaceShip prefab with a Defense component.
  flecs::entity SpaceShip = world.prefab("SpaceShip")
  .set(Defense{50});
  // Create two prefab instances
  flecs::entity inst_1 = world.entity().is_a(SpaceShip);
  flecs::entity inst_2 = world.entity().is_a(SpaceShip);
  // Get instantiated component
  const Defense& d = inst_1.get<Defense>();
  flecs::entity_builder::set
  const Self & set(T &&value) const
  Set a component for an entity.
  Definition builder.hpp:705
  flecs::entity_view::get
  const T & get() const
  Get component value.
  Definition entity_view.hpp:396
  flecs::entity
  Entity.
  Definition entity.hpp:30

- C#

  public record struct Defense(double Value);
  // Create a SpaceShip prefab with a Defense component.
  Entity spaceship = world.Entity("Spaceship")
  .Set(new Defense(50));
  // Create two prefab instances
  Entity inst1 = world.Entity().IsA(spaceship);
  Entity inst2 = world.Entity().IsA(spaceship);
  // Get instantiated component
  ref readonly Defense attack = ref inst1.Get<Defense>();

- Rust

  #[derive(Component)]
  struct Defense {
  value: u32,
  }
  // Create a spaceship prefab with a Defense component.
  let spaceship = world.prefab_named("spaceship").set(Defense { value: 50 });
  // Create two prefab instances
  let inst_1 = world.entity().is_a_id(spaceship);
  let inst_2 = world.entity().is_a_id(spaceship);
  // Get instantiated component
  inst_1.get::<&Defense>(|defense| {
  println!("Defense value: {}", defense.value);
  });

The following sections go over the different aspects of the prefab feature.

# The Prefab tag

Prefabs are regular entities; the only difference is that queries don't match them by default. This allows prefab entities to coexist with regular entities in the same world without impacting game logic. The mechanism used to exclude prefabs from queries is a builtin Prefab tag. The following example shows how to create a prefab:

- C

  ecs_entity_t myPrefab = ecs_new(world);
  ecs_add_id(world, myPrefab, EcsPrefab);
  ecs_add_id
  void ecs_add_id(ecs_world_t *world, ecs_entity_t entity, ecs_id_t component)
  Add a (component) id to an entity.
  ecs_new
  ecs_entity_t ecs_new(ecs_world_t *world)
  Create new entity id.

- C++

  flecs::entity myPrefab = world.entity()
  .add(flecs::Prefab);
  // or the shortcut
  flecs::entity myPrefab = world.prefab();

- C#

  Entity myPrefab = world.Prefab();

- Rust

  let myprefab = world.entity().add::<flecs::Prefab>();
  // or the shortcut
  let myprefab = world.prefab();

Queries don't match prefab entities unless the Prefab tag is explicitly queried for. The following example shows how to match only prefabs by adding the Prefab tag to a query:

- C

  // Only match prefab entities
  ecs_query_t *q = ecs_query(world, {
  .terms = {
  { ecs_id(Position) },
  { EcsPrefab }
  }
  });
  ecs_id
  FLECS_API const ecs_entity_t ecs_id(EcsDocDescription)
  Component id for EcsDocDescription.
  ecs_query
  #define ecs_query(world,...)
  Shorthand for creating a query with ecs_query_cache_init.
  Definition flecs_c.h:262
  ecs_query_t
  Queries are lists of constraints (terms) that match entities.
  Definition flecs.h:813

- C++

  // Only match prefab entities
  world.query_builder<Position>()
  .with(flecs::Prefab)
  .build();

- C#

  // Only match prefab entities
  world.QueryBuilder<Position>()
  .With(Ecs.Prefab)
  .Build();

- Rust

  // Only match prefab entities
  world.query::<&Position>()
  .with::<flecs::Prefab>()
  .build();

> Prefabs are only ignored by queries when they are matched on the $this variable, which is the default for query terms. If a prefab component is matched through query traversal, a fixed term source or variable non-$this source, the query will not ignore the prefab.

To match both regular and prefab entities, make the prefab term optional:

- C

  // Only match prefab entities
  ecs_query_t *q = ecs_query(world, {
  .terms = {
  { ecs_id(Position) },
  { EcsPrefab, .oper = EcsOptional }
  }
  });
  EcsOptional
  @ EcsOptional
  The term may match.
  Definition flecs.h:697

- C++

  // Only match prefab entities
  world.query_builder<Position>()
  .with(flecs::Prefab).optional()
  .build();

- C#

  // Only match prefab entities
  world.QueryBuilder<Position>()
  .With(Ecs.Prefab).Optional()
  .Build();

- Rust

  // Only match prefab entities
  world.query::<&Position>()
  .with::<flecs::Prefab>()
  .optional()
  .build();

Instead of an optional term, queries can also specify a MatchPrefabs flag. This matches the same entities as an optional term, but since the term doesn't need to populate a field slightly improves performance:

- C

  // Only match prefab entities
  ecs_query_t *q = ecs_query(world, {
  .terms = {
  { ecs_id(Position) }
  },
  .flags = EcsQueryMatchPrefab
  });
  EcsQueryMatchPrefab
  #define EcsQueryMatchPrefab
  Query must match prefabs.
  Definition flecs.h:1208

- C++

  // Only match prefab entities
  world.query_builder<Position>()
  .query_flags(EcsQueryMatchPrefab)
  .build();

- C#

  world.QueryBuilder()
  .QueryFlags(Ecs.QueryMatchPrefab)
  .Build();

- Rust

  // Only match prefab entities
  world.query::<&Position>()
  .query_flags(QueryFlags::MatchPrefab)
  .build();

# Component Inheritance

Entities can inherit components from prefabs. Inherited components are only stored once in memory, and shared across instances. This can be useful for static data that's shared across instances, such as material data, textures or meshes.

For a component to be inheritable, it needs to have the (OnInstantiate, Inherit) trait (for more details see the ComponentTraits manual). The following example shows what happens when a prefab with one inheritable and one non-inheritable component is instantiated:

- C

  ECS_COMPONENT(ecs, Health);
  ECS_COMPONENT(ecs, Defense);
  // Make Defense component inheritable
  ecs_add_pair(world, ecs_id(Defense),
  EcsOnInstantiate, EcsInherit);
  // Create prefab
  ecs_entity_t SpaceShip = ecs_entity(ecs, {
  .name = "SpaceShip",
  .add = ecs_ids( EcsPrefab )
  });
  ecs_set(ecs, SpaceShip, Defense, {50});
  ecs_set(ecs, SpaceShip, Health, {100});
  // Create prefab instance
  ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, SpaceShip);
  // Component is retrieved from instance
  const Health *health = ecs_get(world, inst, Health);
  // Component is retrieved from prefab
  const Defense *defense = ecs_get(world, inst, Defense);
  EcsInherit
  const ecs_entity_t EcsInherit
  Inherit component on instantiate.
  EcsOnInstantiate
  const ecs_entity_t EcsOnInstantiate
  Relationship that specifies component inheritance behavior.

- C++

  // Make Defense component inheritable
  world.component<Defense>()
  .add(flecs::OnInstantiate, flecs::Inherit);
  // Create prefab
  flecs::entity SpaceShip = world.prefab()
  .set(Health{100})
  .set(Defense{50});
  // Create prefab instance
  flecs::entity inst = world.entity().is_a(SpaceShip);
  // Component is retrieved from instance
  const Health& health = inst.get<Health>();
  // Component is retrieved from prefab
  const Defense& defense = inst.get<Defense>();

- C#

  // Make Defense component inheritable
  world.Component<Defense>()
  .Add(Ecs.OnInstantiate, Ecs.Inherit);
  // Create prefab
  Entity spaceship = world.Prefab("Spaceship")
  .Set<Health>(new(100))
  .Set<Defense>(new(50));
  // Create a prefab instance
  Entity inst = world.Entity().IsA(spaceship);
  // Component is retrieved from instance
  ref readonly Attack attack = ref inst.Get<Attack>();
  // Component is retrieved from prefab
  ref readonly Defense defense = ref inst.Get<Defense>();

- Rust

  // Make Defense component inheritable
  world
  .component::<Defense>()
  .add_trait::<(flecs::OnInstantiate, flecs::Inherit)>();
  // Create prefab
  let spaceship = world
  .prefab()
  .set(Health { value: 100 })
  .set(Defense { value: 50 });
  // Create prefab instance
  let inst = world.entity().is_a_id(spaceship);
  // Component is retrieved from instance
  inst.get::<&Health>(|health| {
  println!("Health value: {}", health.value);
  });
  // Component is retrieved from prefab
  inst.get::<&Defense>(|defense| {
  println!("Defense value: {}", defense.value);
  });

The owns operation can be used to tell whether a component is owned by the instance or inherited from a prefab:

- C

  if (ecs_owns(world, inst, Defense)) {
  // not inherited
  }

- C++

  if (inst.owns<Defense>()) {
  // not inherited
  }
  flecs::entity_view::owns
  bool owns(flecs::id_t e) const
  Check if entity owns the provided entity.
  Definition entity_view.hpp:1019

- C#

  if (inst.Owns<Defense>()) {
  // not inherited
  }

- Rust

  if inst.owns::<Defense>() {
  // not inherited
  }

The target_for operation can be used to determine from which prefab (or regular entity) a component is inherited:

- C

  ecs_entity_t inherited_from =
  ecs_target_for(world, inst, Defense);
  if (!inherited_from) {
  // not inherited
  }

- C++

  flecs::entity inherited_from =
  inst.target_for<Defense>();
  if (!inherited_from) {
  // not inherited
  }
  flecs::entity_view::target_for
  flecs::entity target_for(flecs::entity_t relationship, flecs::id_t id) const
  Get the target of a pair for a given relationship id.
  Definition impl.hpp:50

- C#

  Entity inheritedFrom = inst.TargetFor<Defense>();
  if (inheritedFrom == 0) {
  // not inherited
  }

- Rust

  let inherited_from = inst.target::<Defense>(0);
  if inherited_from.is_none() {
  // not inherited
  }

# Component Overriding

When an instance inherits a component from a prefab, it can be overridden with a value that's specific to the instance. To override a component, simply add or set it on the instance. The following example shows how:

- C

  ECS_COMPONENT(ecs, Defense);
  // Make Defense component inheritable
  ecs_add_pair(world, ecs_id(Defense),
  EcsOnInstantiate, EcsInherit);
  // Create prefab
  ecs_entity_t SpaceShip = ecs_entity(ecs, {
  .name = "SpaceShip",
  .add = ecs_ids( EcsPrefab )
  });
  ecs_set(ecs, SpaceShip, Defense, {50});
  // Create prefab instances
  ecs_entity_t inst_a = ecs_new_w_pair(world, EcsIsA, SpaceShip);
  ecs_entity_t inst_b = ecs_new_w_pair(world, EcsIsA, SpaceShip);
  // Override Defense only for inst_a
  ecs_set(world, inst_a, Defense, {75});

- C++

  // Make Defense component inheritable
  world.component<Defense>()
  .add(flecs::OnInstantiate, flecs::Inherit);
  // Create prefab
  flecs::entity SpaceShip = world.prefab()
  .set(Defense{50});
  // Create prefab instance
  flecs::entity inst_a = world.entity().is_a(SpaceShip);
  flecs::entity inst_b = world.entity().is_a(SpaceShip);
  // Override Defense only for inst_a
  inst_a.set(Defense{75});

- C#

  // Make Defense component inheritable
  world.Component<Defense>()
  .Add(Ecs.OnInstantiate, Ecs.Inherit);
  // Create prefab
  Entity spaceship = world.Prefab("Spaceship")
  .Set<Defense>(new(50));
  // Create a prefab instance
  Entity instA = world.Entity().IsA(spaceship);
  Entity instB = world.Entity().IsA(spaceship);
  // Override Defense only for instA
  instA.Set(new Defense(75));

- Rust

  // Make Defense component inheritable
  world
  .component::<Defense>()
  .add_trait::<(flecs::OnInstantiate, flecs::Inherit)>();
  // Create prefab
  let spaceship = world.prefab().set(Defense { value: 50 });
  // Create prefab instance
  let inst_a = world.entity().is_a_id(spaceship);
  let inst_b = world.entity().is_a_id(spaceship);
  // Override Defense only for inst_a
  inst_a.set(Defense { value: 75 });

When a component is overridden by adding it to an instance, the component on the instance is initialized with the value from the prefab component. An example:

- C

  ECS_COMPONENT(ecs, Defense);
  // Make Defense component inheritable
  ecs_add_pair(world, ecs_id(Defense),
  EcsOnInstantiate, EcsInherit);
  // Create prefab
  ecs_entity_t SpaceShip = ecs_entity(ecs, {
  .name = "SpaceShip",
  .add = ecs_ids( EcsPrefab )
  });
  ecs_set(ecs, SpaceShip, Defense, {50});
  // Create prefab instances
  ecs_entity_t inst_a = ecs_new_w_pair(world, EcsIsA, SpaceShip);
  ecs_entity_t inst_b = ecs_new_w_pair(world, EcsIsA, SpaceShip);
  // Override Defense only for inst_a
  ecs_add(world, inst_a, Defense); // Initialized with value 50

- C++

  // Make Defense component inheritable
  world.component<Defense>()
  .add(flecs::OnInstantiate, flecs::Inherit);
  // Create prefab
  flecs::entity SpaceShip = world.prefab()
  .set(Defense{50});
  // Create prefab instance
  flecs::entity inst_a = world.entity().is_a(SpaceShip);
  flecs::entity inst_b = world.entity().is_a(SpaceShip);
  // Override Defense only for inst_a
  inst_a.add<Defense>(); // Initialized with value 50
  flecs::entity_builder::add
  const Self & add() const
  Add a component to an entity.
  Definition builder.hpp:25

- C#

  // Make Defense component inheritable
  world.Component<Defense>()
  .Add(Ecs.OnInstantiate, Ecs.Inherit);
  // Create prefab
  Entity spaceship = world.Prefab("Spaceship")
  .Set<Health>(new(100))
  .Set<Defense>(new(50));
  // Create a prefab instance
  Entity instA = world.Entity().IsA(spaceship);
  Entity instB = world.Entity().IsA(spaceship);
  // Override Defense only for instA
  instA.Add<Defense>(); // Initialized with value 50

- Rust

  // Make Defense component inheritable
  world
  .component::<Defense>()
  .add_trait::<(flecs::OnInstantiate, flecs::Inherit)>();
  // Create prefab
  let spaceship = world.prefab().set(Defense { value: 50 });
  // Create prefab instance
  let inst_a = world.entity().is_a_id(spaceship);
  let inst_b = world.entity().is_a_id(spaceship);
  // Override Defense only for inst_a
  inst_a.add::<Defense>(); // Initialized with value 50

When an override is removed, the original value of the prefab is reexposed.

# Auto Overriding

When a component is configured to be inheritable, sometimes it can still be useful for a specific prefab to have the instances always own the component. This can be achieved with an auto override, which flags a component on the prefab to be always overridden on instantiation:

- C

  ECS_COMPONENT(ecs, Defense);
  // Make Defense component inheritable
  ecs_add_pair(world, ecs_id(Defense),
  EcsOnInstantiate, EcsInherit);
  // Create prefab
  ecs_entity_t SpaceShip = ecs_entity(ecs, {
  .name = "SpaceShip",
  .add = ecs_ids( EcsPrefab )
  });
  // Set & auto override Defense
  ecs_set(ecs, SpaceShip, Defense, {50});
  ecs_auto_override(world, SpaceShip, Defense);
  // Create prefab instances
  ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, SpaceShip);
  ecs_owns(world, inst, Defense); // true

- C++

  // Make Defense component inheritable
  world.component<Defense>()
  .add(flecs::OnInstantiate, flecs::Inherit);
  // Create prefab
  flecs::entity SpaceShip = world.prefab()
  .set_auto_override(Defense{50}); // Set & auto override Defense
  // Create prefab instance
  flecs::entity inst = world.entity().is_a(SpaceShip);
  inst.owns<Defense>(); // true
  flecs::entity_builder::set_auto_override
  const Self & set_auto_override(const T &val) const
  Set component, mark component for auto-overriding.
  Definition builder.hpp:445

- C#

  // Make Defense component inheritable
  world.Component<Defense>()
  .Add(Ecs.OnInstantiate, Ecs.Inherit);
  // Create prefab
  Entity spaceship = world.Prefab()
  .SetAutoOverride<Defense>(new(50)); // Set & auto override Defense
  // Create prefab instance
  Entity inst = world.Entity().IsA(spaceship);
  inst.Owns<Defense>(); // true

- Rust

  // Make Defense component inheritable
  world
  .component::<Defense>()
  .add_trait::<(flecs::OnInstantiate, flecs::Inherit)>();
  // Create prefab
  let spaceship = world.prefab().set_auto_override(Defense { value: 50 }); // Set & auto override Defense
  // Create prefab instance
  let inst = world.entity().is_a_id(spaceship);
  inst.owns::<Defense>(); // true

Auto overrides can also be added to prefabs that don't have the actual component. In this case the component is not copied from the prefab (there is nothing to copy), but is added & default constructed on the instance.

This also works for prefab children. Adding an auto override to a child entity without adding the component will add & default construct the component on the instance child.

# Prefab Variants

Prefabs can inherit from each other to create prefab variations without duplicating the prefab data. The following example shows a prefab and a prefab variant.

- C

  ECS_COMPONENT(ecs, Health);
  ECS_COMPONENT(ecs, Defense);
  // Create prefab
  ecs_entity_t SpaceShip = ecs_entity(ecs, {
  .name = "SpaceShip",
  .add = ecs_ids( EcsPrefab )
  });
  ecs_set(ecs, SpaceShip, Defense, {50});
  ecs_set(ecs, SpaceShip, Health, {100});
  // Create prefab variant
  ecs_entity_t freighter = ecs_entity(ecs, {
  .name = "Freighter",
  .add = ecs_ids( EcsPrefab, ecs_isa(SpaceShip) )
  });
  // Override the Health component of the freighter
  ecs_set(ecs, freighter, Health, {150});
  // Create prefab instance
  ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, Freighter);
  const Health *health = ecs_get(world, inst, Health); // 150
  const Defense *defense = ecs_get(world, inst, Defense); // 50

- C++

  // Create prefab
  flecs::entity SpaceShip = world.prefab("SpaceShip")
  .set(Defense{50})
  .set(Health{100});
  // Create prefab variant
  flecs::entity Freighter = world.prefab("Freighter")
  .is_a(SpaceShip)
  .set(Health{150}); // Override the Health component of the freighter
  // Create prefab instance
  flecs::entity inst = world.entity().is_a(Freighter);
  const Health& health = inst.get<Health>(); // 150
  const Defense& defense = inst.get<Defense>(); // 50
  flecs::entity_builder::is_a
  const Self & is_a(entity_t second) const
  Shortcut for add(IsA, entity).
  Definition builder.hpp:213

- C#

  // Create prefab
  Entity spaceship = world.Prefab("Spaceship")
  .Set<Defense>(new(50))
  .Set<Health>(new(100));
  // Create prefab variant
  Entity freighter = world.Prefab("Freighter")
  .IsA(spaceShip)
  .Set<Health>(new(150)); // Override the Health component of the freighter
  // Create prefab instance
  Entity inst = world.Entity().IsA(freighter);
  ref readonly Health health = ref inst.Get<Health>(); // 150
  ref readonly Defense defense = ref inst.Get<Defense>(); // 50

- Rust

  // Create prefab
  let spaceship = world
  .prefab_named("spaceship")
  .set(Defense { value: 50 })
  .set(Health { value: 100 });
  // Create prefab variant
  let freighter = world
  .prefab_named("Freighter")
  .is_a_id(spaceship)
  .set(Health { value: 150 }); // Override the Health component of the freighter
  // Create prefab instance
  let inst = world.entity().is_a_id(freighter);
  inst.get::<&Health>(|health| {
  println!("Health value: {}", health.value); // 150
  });
  inst.get::<&Defense>(|defense| {
  println!("Defense value: {}", defense.value); // 50
  });

# Prefab Hierarchies

When a prefab has children, the entire subtree of a prefab is copied to the instance. Other than with the instance itself where components can be inherited from a prefab, child entities never inherit components from prefab children. Prefab hierarchies are created in the same way as entity hierarchies:

- C

  // Create a prefab hierarchy.
  ecs_entity_t SpaceShip = ecs_entity(ecs, {
  .name = "SpaceShip",
  .add = ecs_ids( EcsPrefab )
  });
  ecs_entity_t Cockpit = ecs_entity(ecs, {
  .name = "Cockpit",
  .parent = SpaceShip, // shortcut to add_pair(EcsChildOf)
  .add = ecs_ids( EcsPrefab )
  });
  // Instantiate the prefab hierarchy
  ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, SpaceShip);
  // Lookup instantiated child
  ecs_entity_t inst_cockpit = ecs_lookup_child(ecs, inst, "Cockpit");
  ecs_lookup_child
  ecs_entity_t ecs_lookup_child(const ecs_world_t *world, ecs_entity_t parent, const char *name)
  Lookup a child entity by name.

- C++

  flecs::entity SpaceShip = world.prefab("SpaceShip");
  flecs::entity Cockpit = world.prefab("Cockpit")
  .child_of(SpaceShip);
  // Instantiate the prefab hierarchy
  flecs::entity inst = ecs.entity().is_a(SpaceShip);
  // Lookup instantiated child
  flecs::entity inst_cockpit = inst.lookup("Cockpit");
  flecs::entity_builder::child_of
  const Self & child_of(entity_t second) const
  Shortcut for add(ChildOf, entity).
  Definition builder.hpp:230
  flecs::entity_view::lookup
  flecs::entity lookup(const char *path, bool search_path=false) const
  Lookup an entity by name.
  Definition impl.hpp:172

- C#

  Entity spaceship = world.Prefab("Spaceship");
  Entity cockpit = world.Prefab("Cockpit")
  .ChildOf(spaceship);
  // Instantiate the prefab hierarchy
  Entity inst = ecs.Entity().IsA(spaceship);
  // Lookup instantiated child
  Entity instCockpit = inst.Lookup("Cockpit");

- Rust

  let spaceship = world.prefab_named("spaceship");
  let cockpit = world.prefab_named("Cockpit").child_of_id(spaceship);
  // Instantiate the prefab hierarchy
  let inst = world.entity().is_a_id(spaceship);
  // Lookup instantiated child
  let inst_cockpit = inst.lookup("Cockpit");

# Prefab Slots

When a prefab hierarchy is instantiated often code will want to refer to a specific instantiated child. A typical example is a turret prefab with a turret head that needs to rotate.

While it is possible to lookup a child by name and store it on a component, this adds boilerplate and reduces efficiency. Prefab slots make this easier.

A prefab child can be created as a slot. Slots are created as relationships on the instance, with as target of the relationship the instantiated child. The slot is added as a DontFragment relationship which doesn't fragment archetypes.

The following example shows how to create and use a prefab slot:

- C

  // Create a prefab hierarchy.
  ecs_entity_t SpaceShip = ecs_entity(ecs, {
  .name = "SpaceShip",
  .add = ecs_ids( EcsPrefab )
  });
  ecs_entity_t Cockpit = ecs_entity(ecs, {
  .name = "Cockpit",
  .parent = SpaceShip,
  .add = ecs_ids(
  EcsPrefab,
  ecs_pair(EcsSlotOf, SpaceShip) // mark as slot
  )
  });
  // Instantiate the prefab hierarchy
  ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, SpaceShip);
  // Lookup instantiated child
  ecs_entity_t inst_cockpit = ecs_target(world, inst, Cockpit, 0);
  EcsSlotOf
  const ecs_entity_t EcsSlotOf
  Used to express a slot (used with prefab inheritance).

- C++

  flecs::entity SpaceShip = world.prefab("SpaceShip");
  flecs::entity Cockpit = world.prefab("Cockpit")
  .child_of(SpaceShip)
  .slot(); // Defaults to (SlotOf, SpaceShip)
  // Instantiate the prefab hierarchy
  flecs::entity inst = ecs.entity().is_a(SpaceShip);
  // Lookup instantiated child
  flecs::entity inst_cockpit = inst.target(CockPit);
  flecs::entity_builder::slot
  const Self & slot() const
  Shortcut for add(SlotOf, target(ChildOf)).
  Definition builder.hpp:263
  flecs::entity_view::target
  flecs::entity target(int32_t index=0) const
  Get target for a given pair.
  Definition impl.hpp:36

- C#

  Entity spaceship = world.Prefab("Spaceship");
  Entity cockpit = world.Prefab("Cockpit")
  .ChildOf(spaceship)
  .SlotOf(spaceship);
  // Instantiate the prefab hierarchy
  Entity inst = ecs.Entity().IsA(spaceship);
  // Lookup instantiated child
  Entity instCockpit = inst.Target(cockpit);

- Rust

  let spaceship = world.prefab_named("Spaceship");
  let cockpit = world.prefab_named("Cockpit").child_of_id(spaceship).slot(); // Defaults to (SlotOf, spaceship)
  // Instantiate the prefab hierarchy
  let inst = world.entity().is_a_id(spaceship);
  // Lookup instantiated child
  let inst_cockpit = inst.target_id(cockpit, 0);

# Prefab Types (C++, C#)

Like entities and components, prefabs can be associated with a C++ type. This makes it easier to instantiate prefabs as it is not necessary to pass prefab handles around in the application. The following example shows how to associate types with prefabs:

- C++

  struct SpaceShip {};
  // Create prefab associated with the SpaceShip type
  world.prefab<SpaceShip>()
  .set<Defense>({ 50 })
  .set<Health>({ 100 });
  // Instantiate prefab with type
  flecs::entity inst = world.entity()
  .is_a<SpaceShip>();
  // Lookup prefab handle
  flecs::entity prefab = world.lookup("SpaceShip");
  flecs::world::prefab
  flecs::entity prefab(Args &&... args) const
  Create a prefab.

- C#

  public struct Spaceship { }
  // Create prefab associated with the Spaceship type
  world.Prefab<Spaceship>()
  .Set<Defense>(new(50))
  .Set<Health>(new(100));
  // Instantiate prefab with type
  Entity inst = world.Entity()
  .IsA<Spaceship>();
  // Lookup prefab handle
  Entity prefab = world.Lookup("Spaceship");

- Rust

  #[derive(Component)]
  struct Spaceship;
  // Create prefab associated with the spaceship type
  world
  .prefab_type::<Spaceship>()
  .set(Defense { value: 50 })
  .set(Health { value: 100 });
  // Instantiate prefab with type
  let inst = world.entity().is_a::<Spaceship>();
  // Lookup prefab handle
  let prefab = world.lookup("spaceship");