# Getting Started with GECS > **Build your first ECS project in 5 minutes** This guide will walk you through creating a simple player entity with health and transform components using GECS. By the end, you'll understand the core concepts and have a working example. ## 📋 Prerequisites - Godot 4.x installed - Basic GDScript knowledge - 5 minutes of your time ## ⚡ Step 1: Setup (1 minute) ### Install GECS 1. **Download GECS** and place it in your project's `addons/` folder 2. **Enable the plugin**: Go to `Project > Project Settings > Plugins` and enable "GECS" 3. **Verify setup**: The ECS singleton should be automatically added to AutoLoad > 💡 **Quick Check**: If you see errors, make sure `ECS` appears in `Project > Project Settings > AutoLoad` ## 🎮 Step 2: Your First Entity (2 minutes) Entities in GECS extend Godot's `Node` class. You have two options for creating entities: ### **Option A: Scene-based Entities** (For spatial properties) Use this when you need access to `Node3D` or `Node2D` properties like position, rotation, scale, or want to add visual children (sprites, meshes, etc.). > ⚠️ **Key Point**: `Entity` extends `Node` (not `Node3D` or `Node2D`), so create a scene with the appropriate spatial node type as the root, then attach your entity script to it. **Steps:** 1. **Create a new scene** in Godot: - Click `Scene > New Scene` or press `Ctrl+N` - Select **"Node3D"** as the root node type (for 3D games) or **"Node2D"** (for 2D games) - Rename the root node to `Player` 2. **Attach the entity script**: - With the root node selected, click the "Attach Script" button (📄+ icon) - Save as `e_player.gd` 3. **Save the scene**: - Save as `e_player.tscn` in your scenes folder **File: `e_player.gd`** ```gdscript # e_player.gd class_name Player extends Entity func on_ready(): # Sync the entity's scene position to the Transform component if has_component(C_Transform): var c_trs = get_component(C_Transform) as C_Transform c_trs.position = self.global_position ``` > 💡 **Use case**: Players, enemies, projectiles, or anything that needs a position in your game world. ### **Option B: Code-based Entities** (Pure data containers) Use this when you DON'T need spatial properties and just want a pure data container (e.g., game managers, abstract systems, timers). ```gdscript # Just extend Entity directly class_name GameManager extends Entity # No scene needed - instantiate with GameManager.new() ``` > 💡 **Use case**: Game state managers, quest trackers, inventory systems, or any non-spatial game logic. --- **For this tutorial**, we'll use **Option A** (scene-based) since we want our player to move around the screen with a position. ## 📦 Step 3: Your First Components (1 minute) Components hold data. Let's create health and transform components: **File: `c_health.gd`** ```gdscript # c_health.gd class_name C_Health extends Component @export var current: float = 100.0 @export var maximum: float = 100.0 func _init(max_health: float = 100.0): maximum = max_health current = max_health ``` **File: `c_transform.gd`** ```gdscript # c_transform.gd class_name C_Transform extends Component @export var position: Vector3 = Vector3.ZERO func _init(pos: Vector3 = Vector3.ZERO): position = pos ``` **File: `c_velocity.gd`** ```gdscript # c_velocity.gd class_name C_Velocity extends Component @export var velocity: Vector3 = Vector3.ZERO func _init(vel: Vector3 = Vector3.ZERO): velocity = vel ``` > 💡 **Key Principle**: Components only hold data, never logic. Think of them as data containers. > ⚠️ **Important Note**: Components `_init` function requires that all arguments have a default value or Godot will crash. ## ⚙️ Step 4: Your First System (1 minute) Systems contain the logic that operates on entities with specific components. This system moves entities across the screen: **File: `s_movement.gd`** ```gdscript # s_movement.gd class_name MovementSystem extends System func query(): # Find all entities that have both transform and velocity return q.with_all([C_Transform, C_Velocity]) func process(entities: Array[Entity], components: Array, delta: float): # Process each entity in the array for entity in entities: var c_trs = entity.get_component(C_Transform) as C_Transform var c_velocity = entity.get_component(C_Velocity) as C_Velocity # Move the entity based on its velocity c_trs.position += c_velocity.velocity * delta # Update the actual entity position in the scene entity.global_position = c_trs.position # Bounce off screen edges (simple example) if c_trs.position.x > 10 or c_trs.position.x < -10: c_velocity.velocity.x *= -1 ``` > 💡 **System Logic**: Query finds entities with required components, process() runs the movement logic on each entity every frame. ## 🎬 Step 5: See It Work (1 minute) Now let's put it all together in a main scene: ### Create Main Scene 1. **Create a new scene** with a `Node` as the root 2. **Add a World node** as a child (Add Child Node > search for "World") 3. **Attach this script** to the root node: **File: `main.gd`** ```gdscript # main.gd extends Node @onready var world: World = $World func _ready(): ECS.world = world # Load and instantiate the player entity scene var player_scene = preload("res://e_player.tscn") # Adjust path as needed var e_player = player_scene.instantiate() as Player # Add components to the entity e_player.add_components([ C_Health.new(100), C_Transform.new(), C_Velocity.new(Vector3(2, 0, 0)) # Move right at 2 units/second ]) add_child(e_player) # Add to scene tree ECS.world.add_entity(e_player) # Add to ECS world # Create the movement system var movement_system = MovementSystem.new() ECS.world.add_system(movement_system) func _process(delta): # Process all systems if ECS.world: ECS.process(delta) ``` **Run your project!** 🎉 You now have a working ECS setup where the player entity moves across the screen and bounces off the edges! The MovementSystem updates entity positions based on their velocity components. > 💡 **Scene-based entities**: Notice we load and instantiate the `e_player.tscn` scene instead of calling `Player.new()`. This is required because we need access to spatial properties (position). For entities that don't need spatial properties, `Entity.new()` works fine. ## 🎯 What You Just Built Congratulations! You've created your first ECS project with: - **Entity**: Player - a container for components - **Components**: C_Health, C_Transform, C_Velocity - pure data containers - **System**: MovementSystem - logic that moves entities based on velocity - **World**: Container that manages entities and systems ## 📈 Next Steps Now that you have the basics working, here's how to level up: ### 1. Create Entity Prefabs (Recommended) Instead of creating entities in code, use Godot's scene system: 1. **Create a new scene** with your Entity class as the root node 2. **Add visual children** (MeshInstance3D, Sprite3D, etc.) 3. **Add components via define_components()** or `component_resources` array in Inspector 4. **Save as .tscn file** (e.g., `e_player.tscn`) 5. **Load and instantiate** in your main scene ```gdscript # Improved e_player.gd with define_components() class_name Player extends Entity func define_components() -> Array: return [ C_Health.new(100), C_Transform.new(), C_Velocity.new(Vector3(1, 0, 0)) # Move right slowly ] func on_ready(): # Sync scene position to component if has_component(C_Transform): var c_trs = get_component(C_Transform) as C_Transform c_trs.position = self.global_position ``` ### 2. Organize Your Main Scene Structure your main scene using the proven scene-based pattern: ``` Main.tscn ├── World (World node) ├── DefaultSystems (instantiated from default_systems.tscn) │ ├── input (SystemGroup) │ ├── gameplay (SystemGroup) │ ├── physics (SystemGroup) │ └── ui (SystemGroup) ├── Level (Node3D for static environment) └── Entities (Node3D for spawned entities) ``` **Benefits:** - **Visual organization** in Godot editor - **Easy system reordering** between groups - **Reusable system configurations** ### 3. Learn More Patterns ### 🧠 Understand the Concepts **→ [Core Concepts Guide](CORE_CONCEPTS.md)** - Deep dive into Entities, Components, Systems, and Relationships ### 🔧 Add More Features Try adding these to your moving player: - **Input system** - Add C_Input component and system to control movement with arrow keys - **Multiple entities** - Create more moving objects with different velocities - **Collision system** - Add C_Collision component and detect when entities hit each other - **Gravity system** - Add downward velocity to make entities fall ### 📚 Learn Best Practices **→ [Best Practices Guide](BEST_PRACTICES.md)** - Write maintainable ECS code ### 🔧 Explore Advanced Features - **[Component Queries](COMPONENT_QUERIES.md)** - Filter by component property values - **[Relationships](RELATIONSHIPS.md)** - Link entities together for complex interactions - **[Observers](OBSERVERS.md)** - Reactive systems that respond to changes - **[Performance Optimization](PERFORMANCE_OPTIMIZATION.md)** - Make your games run fast ## ❓ Having Issues? ### Player not responding? - Check that `ECS.process(delta)` is called in `_process()` - Verify components are added to the entity via `define_components()` or Inspector - Make sure the system is added to the world - Ensure transform synchronization is called in entity's `on_ready()` ### Can't access position/rotation properties? - ⚠️ **Entity extends Node, not Node3D**: To access spatial properties, create a scene with `Node3D` (3D) or `Node2D` (2D) as the root node type - Attach your entity script (that extends `Entity`) to the Node3D/Node2D root - Load and instantiate the scene file (don't use `.new()` for spatial entities) - **If you don't need spatial properties**: Using `Entity.new()` is perfectly fine for pure data containers - See Step 2 for both entity creation approaches ### Errors in console? - Check that all classes extend the correct base class - Verify file names match class names - Ensure GECS plugin is enabled **Still stuck?** → [Troubleshooting Guide](TROUBLESHOOTING.md) ## 🏆 What's Next? You're now ready to build amazing games with GECS! The Entity-Component-System pattern will help you: - **Scale your game** - Add features without breaking existing code - **Reuse code** - Components and systems work across different entity types - **Debug easier** - Clear separation between data and logic - **Optimize performance** - GECS handles efficient querying for you **Ready to dive deeper?** Start with [Core Concepts](CORE_CONCEPTS.md) to really understand what makes ECS powerful. **Need help?** [Join our Discord community](https://discord.gg/eB43XU2tmn) for support and discussions. --- _"The best way to learn ECS is to build with it. Start simple, then add complexity as you understand the patterns."_