Skip to main content

World

Struct World 

Source
pub struct World { /* private fields */ }
Expand description

The central container for all ECS data.

World is the top-level struct that owns all ECS state. It provides methods to spawn/despawn entities, add/remove/query components, and manage archetypes.

§Design Philosophy

The World follows Bevy’s architecture pattern:

  1. Entity allocation is handled by EntityAllocator using generational indices
  2. Component storage uses type-erased SparseSet<T> instances
  3. Archetype tracking groups entities by their component signature
  4. Entity-archetype mapping enables O(1) component lookups

§Type Erasure

Component storage is type-erased using Box<dyn Any + Send + Sync>. This allows the World to store components of any type without being generic. Type safety is maintained through ComponentId keys and careful downcasting.

§Memory Layout

Components are stored in SparseSet<T> instances, one per component type. Entities are tracked in archetypes for efficient querying. The entity_archetypes map provides O(1) lookup of an entity’s archetype.

§Example

use goud_engine::ecs::{World, Component};

// Define components
struct Position { x: f32, y: f32 }
impl Component for Position {}

// Create world
let mut world = World::new();

// World starts with one archetype (empty)
assert_eq!(world.archetype_count(), 1);
assert_eq!(world.entity_count(), 0);

Implementations§

Source§

impl World

Source

pub fn register_cloneable<T>(&mut self)
where T: Component + Clone,

Registers a component type as cloneable.

After registration, entities with this component can have it cloned via clone_entity. Components that are not registered are silently skipped during cloning.

§Type Parameters
  • T: A component type that implements Clone
§Example
use goud_engine::ecs::{World, Component};

#[derive(Debug, Clone, PartialEq)]
struct Health(f32);
impl Component for Health {}

let mut world = World::new();
world.register_cloneable::<Health>();
Source

pub fn register_builtin_cloneables(&mut self)

Registers built-in engine components as cloneable.

This registers the following component types:

  • Transform2D, GlobalTransform2D (2D)
  • Transform, GlobalTransform (3D)
  • Parent, Children, Name

Call this method if you intend to use entity cloning with built-in components. This is opt-in to avoid overhead for applications that do not need cloning.

Source

pub fn clone_entity(&mut self, entity: Entity) -> Option<Entity>

Clones an entity, producing a new entity with copies of all cloneable components.

Components whose types were not registered via register_cloneable are silently skipped.

Hierarchy handling:

  • If the source has a Parent component, the clone will not have one (the clone is detached from the hierarchy).
  • If the source has a Children component, the clone will not have one (children are not shared). Use clone_entity_recursive to deep-clone the subtree.
§Returns

Some(new_entity) if the source entity is alive, None otherwise.

Source

pub fn clone_entity_recursive(&mut self, entity: Entity) -> Option<Entity>

Recursively clones an entity and its entire subtree.

Each child (and descendant) is cloned and re-parented under the corresponding cloned parent, preserving the hierarchy shape.

§Returns

Some(root_clone) if the source entity is alive, None otherwise.

Source§

impl World

Source

pub fn component_type_count(&self) -> usize

Returns the number of registered component types.

A component type is registered when the first entity receives a component of that type. This count represents the number of unique component types that have been used in this world.

§Example
use goud_engine::ecs::World;

let world = World::new();
assert_eq!(world.component_type_count(), 0);
Source

pub fn has_component_type<T>(&self) -> bool
where T: Component,

Checks if a component type has been registered in this world.

A component type is registered when the first entity receives a component of that type, creating storage for it.

§Example
use goud_engine::ecs::{World, Component, ComponentId};

struct Health(f32);
impl Component for Health {}

let world = World::new();

// No components registered yet
assert!(!world.has_component_type::<Health>());
Source

pub fn get<T>(&self, entity: Entity) -> Option<&T>
where T: Component,

Gets an immutable reference to a component on an entity.

Returns None if the entity doesn’t exist or doesn’t have the component.

§Type Parameters
  • T: The component type to retrieve
§Arguments
  • entity - The entity to get the component from
§Returns

Some(&T) if the entity exists and has the component, None otherwise.

§Example
use goud_engine::ecs::{World, Component};

#[derive(Debug, PartialEq)]
struct Position { x: f32, y: f32 }
impl Component for Position {}

let mut world = World::new();

// Entity without Position component
let entity = world.spawn_empty();

// Returns None because entity doesn't have Position
assert!(world.get::<Position>(entity).is_none());
§Performance

This is an O(1) operation using sparse set lookup.

Source

pub fn get_mut<T>(&mut self, entity: Entity) -> Option<&mut T>
where T: Component,

Gets a mutable reference to a component on an entity.

Returns None if the entity doesn’t exist or doesn’t have the component.

§Type Parameters
  • T: The component type to retrieve
§Arguments
  • entity - The entity to get the component from
§Returns

Some(&mut T) if the entity exists and has the component, None otherwise.

§Example
use goud_engine::ecs::{World, Component};

#[derive(Debug, PartialEq)]
struct Health(i32);
impl Component for Health {}

let mut world = World::new();
let entity = world.spawn_empty();

// Entity doesn't have Health yet
assert!(world.get_mut::<Health>(entity).is_none());
§Performance

This is an O(1) operation using sparse set lookup.

Source

pub fn has<T>(&self, entity: Entity) -> bool
where T: Component,

Checks if an entity has a specific component type.

Returns false if the entity doesn’t exist or doesn’t have the component.

§Type Parameters
  • T: The component type to check for
§Arguments
  • entity - The entity to check
§Returns

true if the entity exists and has the component, false otherwise.

§Example
use goud_engine::ecs::{World, Component};

struct Marker;
impl Component for Marker {}

let mut world = World::new();
let entity = world.spawn_empty();

// Entity doesn't have Marker component
assert!(!world.has::<Marker>(entity));
§Performance

This is an O(1) operation using sparse set lookup.

Source

pub fn get_component_added_tick<T>(&self, entity: Entity) -> Option<u32>
where T: Component,

Returns the added tick for a component on an entity.

Returns None if the entity does not have the component.

Source

pub fn get_component_changed_tick<T>(&self, entity: Entity) -> Option<u32>
where T: Component,

Returns the changed tick for a component on an entity.

Returns None if the entity does not have the component.

Source§

impl World

Source

pub fn insert<T>(&mut self, entity: Entity, component: T) -> Option<T>
where T: Component,

Inserts a component on an entity.

If the entity already has a component of this type, it is replaced and the old value is returned. If the entity doesn’t have this component, it is added and the entity transitions to a new archetype.

§Type Parameters
  • T: The component type to insert
§Arguments
  • entity - The entity to add the component to
  • component - The component value to insert
§Returns
  • Some(old_component) if the entity already had this component
  • None if this is a new component for the entity
§Panics

This method does not panic. If the entity is dead, the operation is a no-op and returns None.

§Example
use goud_engine::ecs::{World, Component};

#[derive(Debug, Clone, Copy, PartialEq)]
struct Position { x: f32, y: f32 }
impl Component for Position {}

let mut world = World::new();
let entity = world.spawn_empty();

// First insert returns None
let old = world.insert(entity, Position { x: 1.0, y: 2.0 });
assert!(old.is_none());
assert_eq!(world.get::<Position>(entity), Some(&Position { x: 1.0, y: 2.0 }));

// Second insert returns old value
let old = world.insert(entity, Position { x: 10.0, y: 20.0 });
assert_eq!(old, Some(Position { x: 1.0, y: 2.0 }));
assert_eq!(world.get::<Position>(entity), Some(&Position { x: 10.0, y: 20.0 }));
§Archetype Transitions

When a new component type is added, the entity moves from its current archetype to a new archetype that includes the new component. This is handled automatically by the archetype graph.

§Performance
  • If replacing an existing component: O(1)
  • If adding a new component type: O(k) where k is the number of components on the entity (archetype transition)
Source

pub fn insert_batch<T>( &mut self, batch: impl IntoIterator<Item = (Entity, T)>, ) -> usize
where T: Component,

Inserts components for multiple entities in batch.

This is more efficient than calling insert repeatedly because it can batch archetype lookups and transitions.

§Type Parameters
  • T: The component type to insert
§Arguments
  • batch - An iterator of (entity, component) pairs
§Returns

The number of components successfully inserted (entities that were alive).

§Example
use goud_engine::ecs::{World, Component};

#[derive(Debug, Clone, Copy, PartialEq)]
struct Health(i32);
impl Component for Health {}

let mut world = World::new();
let entities = world.spawn_batch(3);

// Insert health for all entities
let components = vec![
    (entities[0], Health(100)),
    (entities[1], Health(80)),
    (entities[2], Health(50)),
];

let count = world.insert_batch(components);
assert_eq!(count, 3);

assert_eq!(world.get::<Health>(entities[0]), Some(&Health(100)));
assert_eq!(world.get::<Health>(entities[1]), Some(&Health(80)));
assert_eq!(world.get::<Health>(entities[2]), Some(&Health(50)));
§Performance

Batch insertion is more efficient because:

  • Archetype edge lookups are cached after the first transition
  • Storage is accessed once and reused for all insertions
Source

pub fn remove<T>(&mut self, entity: Entity) -> Option<T>
where T: Component,

Removes a component from an entity and returns it.

If the entity has the component, it is removed, the entity transitions to a new archetype (without this component), and the old value is returned. If the entity doesn’t have this component, returns None.

§Type Parameters
  • T: The component type to remove
§Arguments
  • entity - The entity to remove the component from
§Returns
  • Some(component) if the entity had this component
  • None if the entity doesn’t exist, is dead, or doesn’t have this component
§Example
use goud_engine::ecs::{World, Component};

#[derive(Debug, Clone, Copy, PartialEq)]
struct Position { x: f32, y: f32 }
impl Component for Position {}

let mut world = World::new();
let entity = world.spawn().insert(Position { x: 1.0, y: 2.0 }).id();

// Remove returns the component
let removed = world.remove::<Position>(entity);
assert_eq!(removed, Some(Position { x: 1.0, y: 2.0 }));

// Entity no longer has the component
assert!(!world.has::<Position>(entity));

// Removing again returns None
let removed_again = world.remove::<Position>(entity);
assert!(removed_again.is_none());
§Archetype Transitions

When a component is removed, the entity moves from its current archetype to a new archetype that doesn’t include this component. If this was the entity’s last component, it transitions to the empty archetype.

§Performance

This is O(1) for the storage removal plus O(1) archetype transition (using cached edge lookup). The archetype graph caches remove edges for efficient repeated transitions.

Source

pub fn take<T>(&mut self, entity: Entity) -> Option<T>
where T: Component,

Removes a component from an entity and returns it.

This is an alias for remove. The name take follows Rust’s convention for methods that consume/take ownership of data.

§Example
use goud_engine::ecs::{World, Component};

#[derive(Debug, Clone, Copy, PartialEq)]
struct Health(i32);
impl Component for Health {}

let mut world = World::new();
let entity = world.spawn().insert(Health(100)).id();

// take() is identical to remove()
let health = world.take::<Health>(entity);
assert_eq!(health, Some(Health(100)));
Source§

impl World

Source

pub fn entity_count(&self) -> usize

Returns the number of currently alive entities.

This is the total number of entities that have been spawned and not yet despawned.

§Example
use goud_engine::ecs::World;

let world = World::new();
assert_eq!(world.entity_count(), 0);
Source

pub fn is_empty(&self) -> bool

Returns true if there are no entities in the world.

§Example
use goud_engine::ecs::World;

let world = World::new();
assert!(world.is_empty());
Source

pub fn archetype_count(&self) -> usize

Returns the number of archetypes in the world.

This includes the EMPTY archetype which always exists. As entities gain different combinations of components, new archetypes are created.

§Performance Note

A high archetype count can indicate fragmentation. If you have many archetypes with few entities each, consider consolidating component combinations.

§Example
use goud_engine::ecs::World;

let world = World::new();
assert_eq!(world.archetype_count(), 1); // Empty archetype
Source

pub fn spawn_empty(&mut self) -> Entity

Spawns a new entity with no components.

The entity is allocated, added to the empty archetype, and returned. Use this when you want to add components later or need a simple entity.

§Returns

The newly created Entity.

§Example
use goud_engine::ecs::World;

let mut world = World::new();

let entity = world.spawn_empty();

assert!(world.is_alive(entity));
assert_eq!(world.entity_count(), 1);
§Performance

This is an O(1) operation. The entity is immediately available for component additions.

Source

pub fn spawn(&mut self) -> EntityWorldMut<'_>

Spawns a new entity and returns a builder for adding components.

This is the primary way to create entities with components using a fluent builder pattern. The entity is immediately alive and starts in the empty archetype.

§Returns

An EntityWorldMut builder for adding components to the entity.

§Example
use goud_engine::ecs::{World, Component};

struct Position { x: f32, y: f32 }
impl Component for Position {}

let mut world = World::new();

// Spawn with components (insert will be available in step 2.4.5)
let entity = world.spawn()
    .insert(Position { x: 0.0, y: 0.0 })
    .id();

assert!(world.is_alive(entity));
§Builder Pattern

The returned EntityWorldMut holds a mutable borrow of the world. Call .id() at the end of your chain to get the entity ID and release the borrow.

§Performance

Entity spawning is O(1). Adding components via the builder triggers archetype transitions as needed.

Source

pub fn spawn_batch(&mut self, count: usize) -> Vec<Entity>

Spawns multiple entities at once and returns their IDs.

This is more efficient than calling spawn_empty() in a loop because it can batch allocations.

§Arguments
  • count - The number of entities to spawn
§Returns

A vector of the newly created Entity IDs.

§Example
use goud_engine::ecs::World;

let mut world = World::new();

let entities = world.spawn_batch(100);

assert_eq!(entities.len(), 100);
assert_eq!(world.entity_count(), 100);

for entity in &entities {
    assert!(world.is_alive(*entity));
}
§Performance

Batch spawning uses the entity allocator’s batch allocation, which is more efficient than individual allocations. The empty archetype is also updated in bulk.

Source

pub fn despawn(&mut self, entity: Entity) -> bool

Despawns an entity, removing it and all its components from the world.

This completely removes the entity from the ECS:

  • The entity is removed from its archetype
  • All components attached to the entity are dropped
  • The entity ID is deallocated and may be recycled with a new generation
§Arguments
  • entity - The entity to despawn
§Returns

true if the entity was successfully despawned, false if it was already dead or invalid.

§Example
use goud_engine::ecs::World;

let mut world = World::new();

let entity = world.spawn_empty();
assert!(world.is_alive(entity));

let despawned = world.despawn(entity);
assert!(despawned);
assert!(!world.is_alive(entity));

// Despawning again returns false
let despawned_again = world.despawn(entity);
assert!(!despawned_again);
§Component Cleanup

All components attached to the entity are dropped when the entity is despawned. This ensures resources are properly released.

§Performance

Despawning is O(n) where n is the number of component types registered in the world, as we must check each storage for the entity’s components. For better performance with many entities, use despawn_batch.

Source

pub fn despawn_batch(&mut self, entities: &[Entity]) -> usize

Despawns multiple entities at once.

This is more efficient than calling despawn repeatedly because it can batch some operations.

§Arguments
  • entities - A slice of entities to despawn
§Returns

The number of entities successfully despawned. Entities that were already dead or invalid are not counted.

§Example
use goud_engine::ecs::World;

let mut world = World::new();

let entities = world.spawn_batch(10);
assert_eq!(world.entity_count(), 10);

let despawned = world.despawn_batch(&entities);
assert_eq!(despawned, 10);
assert_eq!(world.entity_count(), 0);
§Performance

Batch despawning is more efficient when removing many entities, but the complexity is still O(n * m) where n is the number of entities and m is the number of component types.

Source

pub fn despawn_recursive(&mut self, entity: Entity) -> bool

Despawns the entity and all its descendants recursively.

Walks the hierarchy via Children components, despawning from leaves up to the root. Returns true if the root entity was alive and successfully despawned.

§Arguments
  • entity - The root entity to despawn along with its entire subtree
§Returns

true if the root entity was alive and successfully despawned, false if the root entity was already dead or invalid.

§Example
use goud_engine::ecs::World;
use goud_engine::ecs::components::Children;

let mut world = World::new();
let parent = world.spawn_empty();
let child = world.spawn_empty();
world.insert(parent, Children::from_slice(&[child]));

assert!(world.despawn_recursive(parent));
assert!(!world.is_alive(parent));
assert!(!world.is_alive(child));
§Performance

This is O(n) in the number of descendants. Descendants are collected first to avoid borrow conflicts, then despawned from leaves toward the root.

Source

pub fn is_alive(&self, entity: Entity) -> bool

Checks if an entity is currently alive in this world.

An entity is alive if:

  • It was allocated by this world’s entity allocator
  • It has not been despawned
  • Its generation matches the current slot generation
§Arguments
  • entity - The entity to check
§Returns

true if the entity is valid and alive in this world.

§Example
use goud_engine::ecs::World;
use goud_engine::ecs::Entity;

let world = World::new();

// Placeholder entities are never alive
assert!(!world.is_alive(Entity::PLACEHOLDER));

// Fabricated entities are not alive
let fake = Entity::new(999, 1);
assert!(!world.is_alive(fake));
Source

pub fn entity_archetype(&self, entity: Entity) -> Option<ArchetypeId>

Returns the archetype ID for the given entity.

Returns None if the entity is not alive in this world.

§Arguments
  • entity - The entity to look up
§Example
use goud_engine::ecs::World;
use goud_engine::ecs::Entity;

let world = World::new();

// Non-existent entity has no archetype
let fake = Entity::new(0, 1);
assert!(world.entity_archetype(fake).is_none());
Source§

impl World

Source

pub fn insert_non_send_resource<T>(&mut self, resource: T) -> Option<T>
where T: NonSendResource,

Inserts a non-send resource into the world.

Non-send resources are resources that cannot be safely sent between threads. Unlike regular resources, each non-send resource type can only have one instance and must only be accessed from the main thread.

If a non-send resource of this type already exists, it is replaced and the old value is returned.

§Type Parameters
  • T: The non-send resource type (must implement NonSendResource)
§Arguments
  • resource - The non-send resource value to insert
§Returns
  • Some(old_resource) if a non-send resource of this type was replaced
  • None if this is a new non-send resource type
§Example
use goud_engine::ecs::{World, resource::NonSendResource};
use std::rc::Rc;

struct WindowHandle { id: Rc<u32> }
impl NonSendResource for WindowHandle {}

let mut world = World::new();
world.insert_non_send_resource(WindowHandle { id: Rc::new(42) });

let handle = world.get_non_send_resource::<WindowHandle>().unwrap();
assert_eq!(*handle.id, 42);
Source

pub fn remove_non_send_resource<T>(&mut self) -> Option<T>
where T: NonSendResource,

Removes a non-send resource from the world and returns it.

§Type Parameters
  • T: The non-send resource type to remove
§Returns
  • Some(resource) if the non-send resource existed
  • None if no non-send resource of this type exists
§Example
use goud_engine::ecs::{World, resource::NonSendResource};
use std::rc::Rc;

struct WindowHandle { id: Rc<u32> }
impl NonSendResource for WindowHandle {}

let mut world = World::new();
world.insert_non_send_resource(WindowHandle { id: Rc::new(42) });

let handle = world.remove_non_send_resource::<WindowHandle>();
assert!(handle.is_some());
assert!(world.get_non_send_resource::<WindowHandle>().is_none());
Source

pub fn get_non_send_resource<T>(&self) -> Option<&T>
where T: NonSendResource,

Returns an immutable reference to a non-send resource.

§Type Parameters
  • T: The non-send resource type to access
§Returns
  • Some(&T) if the non-send resource exists
  • None if no non-send resource of this type exists
§Example
use goud_engine::ecs::{World, resource::NonSendResource};
use std::rc::Rc;

struct WindowHandle { id: Rc<u32> }
impl NonSendResource for WindowHandle {}

let mut world = World::new();
world.insert_non_send_resource(WindowHandle { id: Rc::new(42) });

if let Some(handle) = world.get_non_send_resource::<WindowHandle>() {
    println!("Window ID: {}", handle.id);
}
Source

pub fn get_non_send_resource_mut<T>(&mut self) -> Option<&mut T>
where T: NonSendResource,

Returns a mutable reference to a non-send resource.

§Type Parameters
  • T: The non-send resource type to access
§Returns
  • Some(&mut T) if the non-send resource exists
  • None if no non-send resource of this type exists
§Example
use goud_engine::ecs::{World, resource::NonSendResource};
use std::rc::Rc;
use std::cell::RefCell;

struct Counter { value: Rc<RefCell<u32>> }
impl NonSendResource for Counter {}

let mut world = World::new();
world.insert_non_send_resource(Counter { value: Rc::new(RefCell::new(0)) });

if let Some(counter) = world.get_non_send_resource_mut::<Counter>() {
    *counter.value.borrow_mut() += 1;
}
Source

pub fn non_send_resource<T>(&self) -> Option<NonSend<'_, T>>
where T: NonSendResource,

Returns an immutable NonSend wrapper for a non-send resource.

This is the primary way to access non-send resources in systems. The NonSend<T> wrapper implements Deref, allowing direct access to the resource.

§Type Parameters
  • T: The non-send resource type to access
§Returns
  • Some(NonSend<T>) if the non-send resource exists
  • None if no non-send resource of this type exists
§Example
use goud_engine::ecs::{World, resource::NonSendResource};
use std::rc::Rc;

struct WindowHandle { id: Rc<u32> }
impl NonSendResource for WindowHandle {}

let mut world = World::new();
world.insert_non_send_resource(WindowHandle { id: Rc::new(42) });

let handle = world.non_send_resource::<WindowHandle>().unwrap();
println!("Window ID: {}", handle.id);
Source

pub fn non_send_resource_mut<T>(&mut self) -> Option<NonSendMut<'_, T>>
where T: NonSendResource,

Returns a mutable NonSendMut wrapper for a non-send resource.

This is the primary way to mutably access non-send resources in systems. The NonSendMut<T> wrapper implements Deref and DerefMut.

§Type Parameters
  • T: The non-send resource type to access
§Returns
  • Some(NonSendMut<T>) if the non-send resource exists
  • None if no non-send resource of this type exists
§Example
use goud_engine::ecs::{World, resource::NonSendResource};
use std::rc::Rc;
use std::cell::RefCell;

struct Counter { value: Rc<RefCell<u32>> }
impl NonSendResource for Counter {}

let mut world = World::new();
world.insert_non_send_resource(Counter { value: Rc::new(RefCell::new(0)) });

{
    let mut counter = world.non_send_resource_mut::<Counter>().unwrap();
    *counter.value.borrow_mut() += 1;
}
Source

pub fn contains_non_send_resource<T>(&self) -> bool
where T: NonSendResource,

Returns true if a non-send resource of the specified type exists.

§Type Parameters
  • T: The non-send resource type to check
§Example
use goud_engine::ecs::{World, resource::NonSendResource};
use std::rc::Rc;

struct WindowHandle { id: Rc<u32> }
impl NonSendResource for WindowHandle {}

let mut world = World::new();
assert!(!world.contains_non_send_resource::<WindowHandle>());

world.insert_non_send_resource(WindowHandle { id: Rc::new(42) });
assert!(world.contains_non_send_resource::<WindowHandle>());
Source

pub fn non_send_resource_count(&self) -> usize

Returns the number of non-send resources in the world.

§Example
use goud_engine::ecs::{World, resource::NonSendResource};
use std::rc::Rc;

struct WindowHandle { id: Rc<u32> }
impl NonSendResource for WindowHandle {}

struct OpenGLContext { ctx: Rc<u32> }
impl NonSendResource for OpenGLContext {}

let mut world = World::new();
assert_eq!(world.non_send_resource_count(), 0);

world.insert_non_send_resource(WindowHandle { id: Rc::new(1) });
world.insert_non_send_resource(OpenGLContext { ctx: Rc::new(2) });
assert_eq!(world.non_send_resource_count(), 2);
Source

pub fn clear_non_send_resources(&mut self)

Clears all non-send resources from the world.

This removes all non-send resources but leaves entities, components, and regular resources intact.

§Example
use goud_engine::ecs::{World, resource::NonSendResource};
use std::rc::Rc;

struct WindowHandle { id: Rc<u32> }
impl NonSendResource for WindowHandle {}

let mut world = World::new();
world.insert_non_send_resource(WindowHandle { id: Rc::new(42) });

world.clear_non_send_resources();
assert_eq!(world.non_send_resource_count(), 0);
Source§

impl World

Source

pub fn insert_resource<T>(&mut self, resource: T) -> Option<T>
where T: Resource,

Inserts a resource into the world.

Resources are singleton data that exists outside the entity-component model. Unlike components, each resource type can only have one instance.

If a resource of this type already exists, it is replaced and the old value is returned.

§Type Parameters
  • T: The resource type (must implement Send + Sync + 'static)
§Arguments
  • resource - The resource value to insert
§Returns
  • Some(old_resource) if a resource of this type was replaced
  • None if this is a new resource type
§Example
use goud_engine::ecs::World;

struct Time { delta: f32, total: f32 }

let mut world = World::new();
world.insert_resource(Time { delta: 0.016, total: 0.0 });

let time = world.get_resource::<Time>().unwrap();
assert_eq!(time.delta, 0.016);
Source

pub fn remove_resource<T>(&mut self) -> Option<T>
where T: Resource,

Removes a resource from the world and returns it.

§Type Parameters
  • T: The resource type to remove
§Returns
  • Some(resource) if the resource existed
  • None if no resource of this type exists
§Example
use goud_engine::ecs::World;

struct Config { debug: bool }

let mut world = World::new();
world.insert_resource(Config { debug: true });

let config = world.remove_resource::<Config>();
assert!(config.is_some());
assert!(world.get_resource::<Config>().is_none());
Source

pub fn get_resource<T>(&self) -> Option<&T>
where T: Resource,

Returns an immutable reference to a resource.

§Type Parameters
  • T: The resource type to access
§Returns
  • Some(&T) if the resource exists
  • None if no resource of this type exists
§Example
use goud_engine::ecs::World;

struct Score(u32);

let mut world = World::new();
world.insert_resource(Score(100));

if let Some(score) = world.get_resource::<Score>() {
    println!("Score: {}", score.0);
}
Source

pub fn get_resource_mut<T>(&mut self) -> Option<&mut T>
where T: Resource,

Returns a mutable reference to a resource.

§Type Parameters
  • T: The resource type to access
§Returns
  • Some(&mut T) if the resource exists
  • None if no resource of this type exists
§Example
use goud_engine::ecs::World;

struct Score(u32);

let mut world = World::new();
world.insert_resource(Score(100));

if let Some(score) = world.get_resource_mut::<Score>() {
    score.0 += 50;
}

assert_eq!(world.get_resource::<Score>().unwrap().0, 150);
Source

pub fn resource<T>(&self) -> Option<Res<'_, T>>
where T: Resource,

Returns an immutable Res wrapper for a resource.

This is the primary way to access resources in systems. The Res<T> wrapper provides convenient access via Deref.

§Type Parameters
  • T: The resource type to access
§Returns
  • Some(Res<T>) if the resource exists
  • None if no resource of this type exists
§Example
use goud_engine::ecs::World;

struct Time { delta: f32 }

let mut world = World::new();
world.insert_resource(Time { delta: 0.016 });

let time = world.resource::<Time>().unwrap();
assert_eq!(time.delta, 0.016);
Source

pub fn resource_mut<T>(&mut self) -> Option<ResMut<'_, T>>
where T: Resource,

Returns a mutable ResMut wrapper for a resource.

This is the primary way to mutably access resources in systems. The ResMut<T> wrapper provides convenient access via Deref and DerefMut.

§Type Parameters
  • T: The resource type to access
§Returns
  • Some(ResMut<T>) if the resource exists
  • None if no resource of this type exists
§Example
use goud_engine::ecs::World;

struct Score(u32);

let mut world = World::new();
world.insert_resource(Score(100));

{
    let mut score = world.resource_mut::<Score>().unwrap();
    score.0 += 50;
}

assert_eq!(world.get_resource::<Score>().unwrap().0, 150);
Source

pub fn contains_resource<T>(&self) -> bool
where T: Resource,

Returns true if a resource of the specified type exists.

§Type Parameters
  • T: The resource type to check
§Example
use goud_engine::ecs::World;

struct Score(u32);

let mut world = World::new();
assert!(!world.contains_resource::<Score>());

world.insert_resource(Score(100));
assert!(world.contains_resource::<Score>());
Source

pub fn resource_count(&self) -> usize

Returns the number of resources in the world.

§Example
use goud_engine::ecs::World;

struct Score(u32);
struct Time { delta: f32 }

let mut world = World::new();
assert_eq!(world.resource_count(), 0);

world.insert_resource(Score(100));
world.insert_resource(Time { delta: 0.016 });
assert_eq!(world.resource_count(), 2);
Source

pub fn clear_resources(&mut self)

Clears all resources from the world.

This removes all resources but leaves entities and components intact.

§Example
use goud_engine::ecs::World;

struct Score(u32);

let mut world = World::new();
world.insert_resource(Score(100));

world.clear_resources();
assert_eq!(world.resource_count(), 0);
Source§

impl World

Source

pub fn register_serializable<T>(&mut self)
where T: Component + Serialize + for<'de> Deserialize<'de>,

Registers a component type as serializable.

After registration, entities with this component can have it serialized/deserialized via serialize_entity and deserialize_entity_components.

The component type must implement Serialize and Deserialize.

§Type Name Fragility

This method uses std::any::type_name::<T>() to key registered components. The returned type name includes full module paths (e.g., my_game::components::Health). Refactoring code structure or moving components to different modules will change these paths, breaking deserialization of existing scene files that reference the old type names. Plan component module stability accordingly.

§Example
use goud_engine::ecs::{World, Component};

#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
struct Health(f32);
impl Component for Health {}

let mut world = World::new();
world.register_serializable::<Health>();
Source

pub fn register_builtin_serializables(&mut self)

Registers built-in engine components as serializable.

Registers all standard engine components for serialization:

  • Transform2D, Transform (local transforms only)
  • Parent, Children, Name
  • Sprite, SpriteAnimator
  • RigidBody, Collider
  • AudioSource
§Global Transforms Excluded

GlobalTransform2D and GlobalTransform are not registered because they are system-computed values derived from local transforms and the hierarchy tree. They must be re-derived by the transform propagation system after deserialization, not loaded from scene files. Loading stale global transforms would violate the invariant that global transforms match parent-to-child propagation.

Call this if you intend to serialize/deserialize entities with built-in components. This is opt-in.

Source

pub fn serialize_entity(&self, entity: Entity) -> Option<Value>

Serializes an entity and all its serializable components to JSON.

Returns a JSON object with the entity ID and a map of component type names to their serialized values. Components not registered via register_serializable are silently skipped.

§Returns

Some(json) if the entity is alive, None otherwise.

§JSON Format
{
    "entity": { "index": 0, "generation": 0 },
    "components": {
        "my_game::Position": { "x": 1.0, "y": 2.0 },
        "my_game::Velocity": { "x": 0.0, "y": -9.8 }
    }
}
Source

pub fn deserialize_entity_components( &mut self, entity: Entity, json: &Value, ) -> usize

Deserializes components from JSON and inserts them onto an entity.

Reads the “components” map from the JSON and inserts each component whose type name is registered via register_serializable.

§Returns

The number of components successfully deserialized and inserted.

Source§

impl World

Source

pub fn new() -> World

Creates a new, empty world.

The world starts with:

  • No entities
  • No component storage
  • One archetype (the EMPTY archetype)
§Example
use goud_engine::ecs::World;

let world = World::new();
assert_eq!(world.entity_count(), 0);
assert_eq!(world.archetype_count(), 1);
Source

pub fn with_capacity( entity_capacity: usize, component_type_capacity: usize, ) -> World

Creates a new world with pre-allocated capacity.

Use this when you know approximately how many entities and component types you’ll have, to avoid reallocations during gameplay.

§Arguments
  • entity_capacity - Expected number of entities
  • component_type_capacity - Expected number of unique component types
§Example
use goud_engine::ecs::World;

// Pre-allocate for a game with ~10,000 entities and ~50 component types
let world = World::with_capacity(10_000, 50);
assert_eq!(world.entity_count(), 0);
Source

pub fn entities(&self) -> &EntityAllocator

Returns a reference to the entity allocator.

This is primarily for internal use and debugging.

Source

pub fn archetypes(&self) -> &ArchetypeGraph

Returns a reference to the archetype graph.

This is primarily for internal use and debugging.

Source

pub fn clear(&mut self)

Clears all entities and components from the world.

After calling this:

  • All entities are invalid (even if you hold references)
  • All component storage is cleared
  • Archetypes remain but are empty
§Use Case

Useful for level transitions or resetting game state without recreating the world.

§Example
use goud_engine::ecs::World;

let mut world = World::new();
// ... spawn entities, add components ...

world.clear();
assert_eq!(world.entity_count(), 0);
Source

pub fn change_tick(&self) -> u32

Returns the current change tick.

Source

pub fn last_change_tick(&self) -> u32

Returns the change tick from the end of the previous system run.

Source

pub fn increment_change_tick(&mut self) -> u32

Increments the change tick and returns the new value.

Source

pub fn set_last_change_tick(&mut self, tick: u32)

Sets the last change tick (typically called at the end of a system).

Trait Implementations§

Source§

impl Debug for World

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for World

Source§

fn default() -> World

Creates an empty world.

Equivalent to World::new().

Auto Trait Implementations§

§

impl Freeze for World

§

impl !RefUnwindSafe for World

§

impl !Send for World

§

impl !Sync for World

§

impl Unpin for World

§

impl UnsafeUnpin for World

§

impl !UnwindSafe for World

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<R, P> ReadPrimitive<R> for P
where R: Read + ReadEndian<P>, P: Default,

Source§

fn read_from_little_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_little_endian().
Source§

fn read_from_big_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_big_endian().
Source§

fn read_from_native_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_native_endian().
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,