component initialization
Guide for component initialization
Component Initialization Patterns
Overview
This document describes the pattern for initializing player components when spawning the player entity.
Component Categories
1. Marker Components
Components that identify the entity type.
Player // Marker component for player entityPurpose: Used in queries to filter for player-specific systems.
2. Spatial Components
Components that define the entity's position and visibility in the world.
SpatialBundle {
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
}Includes:
Transform: Local position, rotation, scaleGlobalTransform: World-space position (computed)Visibility: Whether entity is visibleInheritedVisibility: Visibility inherited from parent (computed)
Why SpatialBundle: Provides all spatial components in one bundle, ensuring consistency.
3. Gameplay State Components
Components that track player progression and state.
crate::systems::player::skills::Skills::default()
crate::systems::player::inventory::Inventory::new(28)
crate::systems::player::inventory::Equipment::default()
crate::systems::player::bank::Bank::default()
crate::systems::player::prayer::PrayerPoints::new(1) // Based on Prayer levelInitialization Patterns:
Skills: UsesDefaulttrait (all skills start at level 1, XP 0)Inventory: Requires capacity parameter (28 slots for player)Equipment: UsesDefaulttrait (all slots empty)Bank: UsesDefaulttrait (empty bank)PrayerPoints: Should usenew(level)constructor, notdefault()
4. Movement Components
Components that control entity movement and pathfinding.
MovementTarget(Vec3::new(0.0, 0.5, 0.0))
crate::systems::ai::pathfinding::PathAgent::default() // ❌ Module not foundPurpose:
MovementTarget: Destination for movement systemPathAgent: Pathfinding state and configuration
Issue:
PathAgent is not found in crate::systems::ai::pathfinding. Need to verify correct path or remove if not needed.5. Debug Components
Components for debugging and identification.
Name::new("Hero")Purpose: Human-readable name for entity inspector and logs.
Component Initialization Best Practices
1. Use Constructors Over Default
Some components have specific initialization requirements:
❌ Bad:
PrayerPoints::default() // Compilation error: no Default trait✅ Good:
PrayerPoints::new(prayer_level) // Uses Prayer level to calculate max points2. Verify Module Paths
Ensure all component types are accessible:
❌ Bad:
crate::systems::ai::pathfinding::PathAgent::default() // Module not found✅ Good:
// Option 1: Fix the path
crate::systems::player::pathfinding::PathAgent::default()
// Option 2: Remove if not needed
// (PathAgent might not be necessary for player movement)3. Bundle Related Components
Use bundles for groups of related components:
SpatialBundle {
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
}This is better than:
Transform::from_xyz(0.0, 0.5, 0.0),
GlobalTransform::default(),
Visibility::default(),
InheritedVisibility::default(),4. Defer Optional Components
Not all components need to be added at spawn time. Some can be added later by systems:
Spawn Time (required for basic functionality):
PlayermarkerSpatialBundle(position/visibility)Skills(gameplay state)Inventory(gameplay state)
Deferred (added by
ensure_player_components or other systems):CombatBonuses(added byensure_player_components)AttackStyle(added byensure_player_components)Luck(added byensure_player_components)- Visual mesh (added by
ensure_player_visuals)
Component Dependencies
Some components depend on others being present:
Player (marker)
├── SpatialBundle (required for position)
├── Skills (required for level-based calculations)
│ └── PrayerPoints (depends on Prayer level)
├── Inventory (required for item storage)
└── Equipment (required for equipped items)Initialization Order:
- Spawn entity with all components in one
commands.spawn()call - Bevy processes the spawn in the next frame
- Systems like
ensure_player_componentsadd missing components - Systems like
ensure_player_visualsadd visual representation
Example: Complete Player Spawn
pub fn spawn_player(
mut commands: Commands,
query: Query<Entity, With<Player>>,
) {
if !query.is_empty() {
return; // Player already exists
}
info!("Spawning Player Entity...");
// Get initial Prayer level from Skills (or default to 1)
let initial_prayer_level = 1;
commands.spawn((
// Marker
Player,
// Spatial
SpatialBundle {
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
},
// Gameplay State
crate::systems::player::skills::Skills::default(),
crate::systems::player::inventory::Inventory::new(28),
crate::systems::player::inventory::Equipment::default(),
crate::systems::player::bank::Bank::default(),
crate::systems::player::prayer::PrayerPoints::new(initial_prayer_level),
// Movement
MovementTarget(Vec3::new(0.0, 0.5, 0.0)),
// Debug
Name::new("Hero"),
));
}Testing Component Initialization
After spawning, verify all components are present:
fn verify_player_components(
player_query: Query<(
&Player,
&Transform,
&Skills,
&Inventory,
&Equipment,
&Bank,
&PrayerPoints,
)>,
) {
if let Ok((_, transform, skills, inventory, equipment, bank, prayer)) = player_query.get_single() {
info!("Player spawned at: {:?}", transform.translation);
info!("Skills: {:?}", skills);
info!("Inventory slots: {}", inventory.items.len());
info!("Prayer points: {}/{}", prayer.current, prayer.max);
} else {
warn!("Player entity missing required components!");
}
}This system can run on
Update to verify the player is properly initialized.