Expand description
Ergonomic smart-pointer-like access to Bevy ECS entities.
This crate provides two complementary approaches for accessing entity data with immutable-only semantics (functional programming style):
§Type Hierarchy
Entity (Bevy's raw type)
│
├── EntityHandle (newtype, safe, explicit world param)
│ └── .bind(world) → BoundEntity<'w> (scoped access)
│
└── WorldRef::entity() → EntityPtr (smart pointer, 'static world)§Choosing Between Types
| Type | Safety | Ergonomics | Use When |
|---|---|---|---|
EntityHandle | ✅ Fully safe | Explicit world param | Store in components |
BoundEntity<'w> | ✅ Fully safe | Scoped lifetime | Simple access, compiler-checked |
EntityPtr | ✅ Safe API* | No lifetime params | Tree/graph traversal, recursion |
*One internal unsafe hidden by WorldExt extension trait
Recommendation: Start with BoundEntity<'w>. Use EntityPtr when lifetime
annotations become cumbersome for complex traversal.
§Safe Approach: EntityHandle + BoundEntity
Use this when you want fully safe code with explicit world parameters:
use bevy_ecs::prelude::*;
use bevy_entity_ptr::{EntityHandle, BoundEntity};
#[derive(Component)]
struct Target(EntityHandle);
#[derive(Component)]
struct Name(&'static str);
// BoundEntity provides fluent access with explicit world parameter
fn get_target_name<'w>(entity: Entity, world: &'w World) -> Option<&'w str> {
let bound = EntityHandle::new(entity).bind(world);
let target = bound.follow::<Target, _>(|t| t.0)?;
target.get::<Name>().map(|n| n.0)
}§Ergonomic Approach: WorldExt + EntityPtr
Use this when you want fluent traversal without passing &World everywhere.
The WorldExt trait hides the internal unsafe, providing a clean API.
use bevy_ecs::prelude::*;
use bevy_entity_ptr::{WorldExt, EntityPtr, EntityHandle};
#[derive(Component)]
struct Target(EntityHandle);
#[derive(Component)]
struct Name(&'static str);
// EntityPtr carries its world reference — no &World threading needed
fn get_target_name(ptr: EntityPtr) -> Option<&'static str> {
let target = ptr.follow::<Target, _>(|t| t.0)?;
target.get::<Name>().map(|n| n.0)
}
// Usage: world.entity_ptr(entity) creates an EntityPtr
fn example(world: &World, entity: Entity) {
let ptr = world.entity_ptr(entity);
if let Some(name) = get_target_name(ptr) {
println!("Target: {}", name);
}
}§Thread Safety
| Type | Send | Sync | Notes |
|---|---|---|---|
EntityHandle | Yes | Yes | Safe to store in components |
BoundEntity | No | No | Borrows &World |
WorldRef | No | No | System-scoped only |
EntityPtr | No | No | System-scoped only |
§Feature Flags
nav-traits: EnablesHasParentandHasChildrentraits for parent/child navigation
§Design Principles
- Immutable only - No
get_mutvariants (functional style) - Single unsafe boundary - Only
WorldRef::new()is unsafe - Graceful stale handling - Despawned entities return
None, not UB - Zero-cost where possible -
#[repr(transparent)],#[inline],const fn
§Safety
The WorldExt::entity_ptr() method internally transmutes &World to
&'static World so that EntityPtr can carry the world reference without
a lifetime parameter. Because the 'static lifetime is fabricated, the
compiler cannot catch use-after-free on the world reference.
This is sound within Bevy systems because:
&Worldis guaranteed to outlive the system scopeEntityPtris!Send, so it cannot escape to other threads- The World cannot be mutated while a system holds
&World
This is NOT sound in arbitrary code where a World could be dropped
while EntityPtr instances still exist — the fabricated 'static lifetime
means the compiler won’t prevent this. If you use WorldExt::entity_ptr()
outside of a Bevy system, you must ensure the World outlives all
EntityPtr instances created from it.
For fully safe code with no soundness caveats, use EntityHandle and
BoundEntity instead — they carry proper lifetime parameters.
Structs§
- Bound
Entity - An entity bound to a world reference for fluent, scoped access.
- Bound
Entity Nav - Navigation wrapper for
BoundEntity, providing parent/children traversal. - Entity
Handle - A lightweight handle to an entity that can be stored in components.
- Entity
Ptr - An ergonomic smart pointer to an entity with embedded World reference.
- Entity
PtrNav - Navigation wrapper for
EntityPtr, providing parent/children traversal. - Entity
PtrNav Many - Many-navigation wrapper for
EntityPtr, for collecting multiple related entities. - World
Ref - A reference to a World with erased lifetime for ergonomic entity traversal.
Traits§
- HasChildren
- Trait for components that reference child entities.
- HasParent
- Trait for components that reference a parent entity.
- World
Ext - Extension trait for
Worldproviding ergonomic entity access methods.