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:
- Entity allocation is handled by
EntityAllocatorusing generational indices - Component storage uses type-erased
SparseSet<T>instances - Archetype tracking groups entities by their component signature
- 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
impl World
Sourcepub fn register_cloneable<T>(&mut self)
pub fn register_cloneable<T>(&mut self)
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 implementsClone
§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>();Sourcepub fn register_builtin_cloneables(&mut self)
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.
Sourcepub fn clone_entity(&mut self, entity: Entity) -> Option<Entity>
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
Parentcomponent, the clone will not have one (the clone is detached from the hierarchy). - If the source has a
Childrencomponent, the clone will not have one (children are not shared). Useclone_entity_recursiveto deep-clone the subtree.
§Returns
Some(new_entity) if the source entity is alive, None otherwise.
Sourcepub fn clone_entity_recursive(&mut self, entity: Entity) -> Option<Entity>
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
impl World
Sourcepub fn component_type_count(&self) -> usize
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);Sourcepub fn has_component_type<T>(&self) -> boolwhere
T: Component,
pub fn has_component_type<T>(&self) -> boolwhere
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>());Sourcepub fn get<T>(&self, entity: Entity) -> Option<&T>where
T: Component,
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.
Sourcepub fn get_mut<T>(&mut self, entity: Entity) -> Option<&mut T>where
T: Component,
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.
Sourcepub fn has<T>(&self, entity: Entity) -> boolwhere
T: Component,
pub fn has<T>(&self, entity: Entity) -> boolwhere
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§impl World
impl World
Sourcepub fn insert<T>(&mut self, entity: Entity, component: T) -> Option<T>where
T: Component,
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 tocomponent- The component value to insert
§Returns
Some(old_component)if the entity already had this componentNoneif 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)
Sourcepub fn insert_batch<T>(
&mut self,
batch: impl IntoIterator<Item = (Entity, T)>,
) -> usizewhere
T: Component,
pub fn insert_batch<T>(
&mut self,
batch: impl IntoIterator<Item = (Entity, T)>,
) -> usizewhere
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
Sourcepub fn remove<T>(&mut self, entity: Entity) -> Option<T>where
T: Component,
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 componentNoneif 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.
Sourcepub fn take<T>(&mut self, entity: Entity) -> Option<T>where
T: Component,
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
impl World
Sourcepub fn entity_count(&self) -> usize
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);Sourcepub fn is_empty(&self) -> bool
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());Sourcepub fn archetype_count(&self) -> usize
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 archetypeSourcepub fn spawn_empty(&mut self) -> Entity
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.
Sourcepub fn spawn(&mut self) -> EntityWorldMut<'_>
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.
Sourcepub fn spawn_batch(&mut self, count: usize) -> Vec<Entity>
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.
Sourcepub fn despawn(&mut self, entity: Entity) -> bool
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.
Sourcepub fn despawn_batch(&mut self, entities: &[Entity]) -> usize
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.
Sourcepub fn despawn_recursive(&mut self, entity: Entity) -> bool
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.
Sourcepub fn is_alive(&self, entity: Entity) -> bool
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));Sourcepub fn entity_archetype(&self, entity: Entity) -> Option<ArchetypeId>
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
impl World
Sourcepub fn insert_non_send_resource<T>(&mut self, resource: T) -> Option<T>where
T: NonSendResource,
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 implementNonSendResource)
§Arguments
resource- The non-send resource value to insert
§Returns
Some(old_resource)if a non-send resource of this type was replacedNoneif 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);Sourcepub fn remove_non_send_resource<T>(&mut self) -> Option<T>where
T: NonSendResource,
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 existedNoneif 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());Sourcepub fn get_non_send_resource<T>(&self) -> Option<&T>where
T: NonSendResource,
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 existsNoneif 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);
}Sourcepub fn get_non_send_resource_mut<T>(&mut self) -> Option<&mut T>where
T: NonSendResource,
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 existsNoneif 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;
}Sourcepub fn non_send_resource<T>(&self) -> Option<NonSend<'_, T>>where
T: NonSendResource,
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 existsNoneif 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);Sourcepub fn non_send_resource_mut<T>(&mut self) -> Option<NonSendMut<'_, T>>where
T: NonSendResource,
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 existsNoneif 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;
}Sourcepub fn contains_non_send_resource<T>(&self) -> boolwhere
T: NonSendResource,
pub fn contains_non_send_resource<T>(&self) -> boolwhere
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>());Sourcepub fn non_send_resource_count(&self) -> usize
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);Sourcepub fn clear_non_send_resources(&mut self)
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
impl World
Sourcepub fn insert_resource<T>(&mut self, resource: T) -> Option<T>where
T: Resource,
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 implementSend + Sync + 'static)
§Arguments
resource- The resource value to insert
§Returns
Some(old_resource)if a resource of this type was replacedNoneif 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);Sourcepub fn remove_resource<T>(&mut self) -> Option<T>where
T: Resource,
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 existedNoneif 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());Sourcepub fn get_resource<T>(&self) -> Option<&T>where
T: Resource,
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 existsNoneif 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);
}Sourcepub fn get_resource_mut<T>(&mut self) -> Option<&mut T>where
T: Resource,
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 existsNoneif 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);Sourcepub fn resource<T>(&self) -> Option<Res<'_, T>>where
T: Resource,
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 existsNoneif 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);Sourcepub fn resource_mut<T>(&mut self) -> Option<ResMut<'_, T>>where
T: Resource,
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 existsNoneif 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);Sourcepub fn contains_resource<T>(&self) -> boolwhere
T: Resource,
pub fn contains_resource<T>(&self) -> boolwhere
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>());Sourcepub fn resource_count(&self) -> usize
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);Sourcepub fn clear_resources(&mut self)
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
impl World
Sourcepub fn register_serializable<T>(&mut self)
pub fn register_serializable<T>(&mut self)
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>();Sourcepub fn register_builtin_serializables(&mut self)
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.
Sourcepub fn serialize_entity(&self, entity: Entity) -> Option<Value>
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 }
}
}Sourcepub fn deserialize_entity_components(
&mut self,
entity: Entity,
json: &Value,
) -> usize
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
impl World
Sourcepub fn new() -> World
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);Sourcepub fn with_capacity(
entity_capacity: usize,
component_type_capacity: usize,
) -> World
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 entitiescomponent_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);Sourcepub fn entities(&self) -> &EntityAllocator
pub fn entities(&self) -> &EntityAllocator
Returns a reference to the entity allocator.
This is primarily for internal use and debugging.
Sourcepub fn archetypes(&self) -> &ArchetypeGraph
pub fn archetypes(&self) -> &ArchetypeGraph
Returns a reference to the archetype graph.
This is primarily for internal use and debugging.
Sourcepub fn clear(&mut self)
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);Sourcepub fn change_tick(&self) -> u32
pub fn change_tick(&self) -> u32
Returns the current change tick.
Sourcepub fn last_change_tick(&self) -> u32
pub fn last_change_tick(&self) -> u32
Returns the change tick from the end of the previous system run.
Sourcepub fn increment_change_tick(&mut self) -> u32
pub fn increment_change_tick(&mut self) -> u32
Increments the change tick and returns the new value.
Sourcepub fn set_last_change_tick(&mut self, tick: u32)
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§
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> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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 moreSource§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian().