Querying with Node Type Markers
When godot-bevy discovers nodes in your Godot scene tree, it automatically creates ECS entities with GodotNodeHandle components to represent them. To enable efficient, type-safe querying, the library also adds marker components that indicate what type of Godot node each entity represents.
Overview
Every entity that represents a Godot node gets marker components automatically:
#![allow(unused)] fn main() { use godot_bevy::prelude::*; // Query all Sprite2D entities - no runtime type checking needed! fn update_sprites(mut sprites: Query<&mut GodotNodeHandle, With<Sprite2DMarker>>) { for mut handle in sprites.iter_mut() { // We know this is a Sprite2D, so .get() is safe let sprite = handle.get::<Sprite2D>(); // Work with the sprite... } } }
Available Marker Components
Base Node Types
NodeMarker- All nodes (every entity gets this)Node2DMarker- All 2D nodesNode3DMarker- All 3D nodesControlMarker- UI control nodesCanvasItemMarker- Canvas items
Visual Nodes
Sprite2DMarker/Sprite3DMarkerAnimatedSprite2DMarker/AnimatedSprite3DMarkerMeshInstance2DMarker/MeshInstance3DMarker
Physics Bodies
RigidBody2DMarker/RigidBody3DMarkerCharacterBody2DMarker/CharacterBody3DMarkerStaticBody2DMarker/StaticBody3DMarker
Areas and Collision
Area2DMarker/Area3DMarkerCollisionShape2DMarker/CollisionShape3DMarkerCollisionPolygon2DMarker/CollisionPolygon3DMarker
Audio Players
AudioStreamPlayerMarkerAudioStreamPlayer2DMarkerAudioStreamPlayer3DMarker
UI Elements
LabelMarkerButtonMarkerLineEditMarkerTextEditMarkerPanelMarker
Cameras and Lighting
Camera2DMarker/Camera3DMarkerDirectionalLight3DMarkerSpotLight3DMarker
Animation and Timing
AnimationPlayerMarkerAnimationTreeMarkerTimerMarker
Path Nodes
Path2DMarker/Path3DMarkerPathFollow2DMarker/PathFollow3DMarker
Hierarchical Markers
Node type markers follow Godot's inheritance hierarchy. For example, a CharacterBody2D entity will have:
NodeMarker(all nodes inherit from Node)Node2DMarker(CharacterBody2D inherits from Node2D)CharacterBody2DMarker(the specific type)
This lets you query at any level of specificity:
#![allow(unused)] fn main() { // Query ALL nodes fn system1(nodes: Query<&GodotNodeHandle, With<NodeMarker>>) { /* ... */ } // Query all 2D nodes fn system2(nodes_2d: Query<&GodotNodeHandle, With<Node2DMarker>>) { /* ... */ } // Query only CharacterBody2D nodes fn system3(characters: Query<&GodotNodeHandle, With<CharacterBody2DMarker>>) { /* ... */ } }
Advanced Query Patterns
Combining Markers
#![allow(unused)] fn main() { // Entities that have BOTH a Sprite2D AND a RigidBody2D fn physics_sprites( query: Query<&mut GodotNodeHandle, (With<Sprite2DMarker>, With<RigidBody2DMarker>)> ) { for mut handle in query.iter_mut() { let sprite = handle.get::<Sprite2D>(); let body = handle.get::<RigidBody2D>(); // Work with both components... } } }
Excluding Node Types
#![allow(unused)] fn main() { // All sprites EXCEPT character bodies (e.g., environmental sprites) fn environment_sprites( query: Query<&mut GodotNodeHandle, (With<Sprite2DMarker>, Without<CharacterBody2DMarker>)> ) { for mut handle in query.iter_mut() { // These are sprites but not character bodies let sprite = handle.get::<Sprite2D>(); // Work with environmental sprites... } } }
Multiple Specific Types
#![allow(unused)] fn main() { // Handle different audio player types efficiently fn update_audio_system( players_1d: Query<&mut GodotNodeHandle, With<AudioStreamPlayerMarker>>, players_2d: Query<&mut GodotNodeHandle, With<AudioStreamPlayer2DMarker>>, players_3d: Query<&mut GodotNodeHandle, With<AudioStreamPlayer3DMarker>>, ) { // Process each type separately - no runtime type checking! for mut handle in players_1d.iter_mut() { let player = handle.get::<AudioStreamPlayer>(); // Handle 1D audio... } for mut handle in players_2d.iter_mut() { let player = handle.get::<AudioStreamPlayer2D>(); // Handle 2D spatial audio... } for mut handle in players_3d.iter_mut() { let player = handle.get::<AudioStreamPlayer3D>(); // Handle 3D spatial audio... } } }
Performance Benefits
Node type markers provide significant performance improvements:
- Reduced Iteration: Only process entities you care about
- No Runtime Type Checking: Skip
try_get()calls - Better ECS Optimization: Bevy can optimize queries with markers
- Cache Efficiency: Process similar entities together
Automatic Application
You don't need to add marker components manually. The library automatically:
- Detects the Godot node type during scene tree traversal
- Adds the appropriate marker component(s) to the entity
- Includes all parent type markers in the inheritance hierarchy
- Ensures every entity gets the base
NodeMarker
This happens transparently when nodes are discovered in your scene tree, making the markers immediately available for your systems to use.
Best Practices
- Use specific markers when you know the exact node type:
With<Sprite2DMarker> - Use hierarchy markers for broader categories:
With<Node2DMarker>for all 2D nodes - Combine markers to find entities with multiple components
- Prefer
.get()over.try_get()when using markers - it's both faster and safer
For migration information from pre-0.7.0 versions, see the Migration Guide.