godot-genre-rts

$npx mdskill add thedivergentai/GD-Agentic-Skills/godot-genre-rts

Build real-time strategy games with unit selection, pathfinding, fog of war, and AI.

  • Solves RTS development complexity including unit selection, command systems, and resource economy.
  • Depends on Godot 4.7+ with NavigationAgent2D, SubViewport shaders, and behavior trees.
  • Recommends patterns based on expert anti-patterns and performance best practices for RTS games.
  • Delivers a structured blueprint with code patterns and configuration guidelines for developers.

SKILL.md

.github/skills/godot-genre-rtsView on GitHub ↗
---
name: godot-genre-rts
description: "Expert blueprint for real-time strategy games including unit selection (drag box, shift-add), command systems (move, attack, gather), pathfinding (NavigationAgent2D with RVO avoidance), fog of war (SubViewport mask shader), resource economy (gather/build loop), and AI opponents (behavior trees, utility AI). Use for base-building RTS or tactical combat games. Trigger keywords: RTS, unit_selection, command_system, fog_of_war, pathfinding_RVO, resource_economy, command_queue."
---

## Godot 4.7 Baseline

- Expert patterns in this skill target **Godot 4.7+** (stable, 2026-06-18).
- Consult the [Godot 4.7 migration guide](https://docs.godotengine.org/en/4.7/tutorials/migrating/upgrading_to_godot_4.7.html) when upgrading projects from 4.6.
- **NEVER** assume 4.6 defaults (stretch mode, audio area_mask, RichTextLabel percent flags) without checking 4.7 migration notes.

# Genre: Real-Time Strategy (RTS)

Expert blueprint for RTS games balancing strategy, micromanagement, and performance.

## NEVER Do (Expert Anti-Patterns)

### Unit Logic & Pathfinding
- NEVER allow pathfinding "Jitter" when moving group units; strictly **stagger path queries** and enable **RVO Avoidance** only when units are in motion to save CPU cycles.
- NEVER update RVO avoidance every frame for all units; strictly use **Avoidance Threading** (Project Settings) and replace static units with `NavigationObstacle`.
- NEVER let units get stuck in infinite path loops; strictly implement a **timeout and IDLE state** if a destination is unreachable.
- NEVER use `_process()` on hundreds of individual units; strictly use a central **UnitManager** or `_physics_process` only when required.
- NEVER calculate unit visibility manually for Fog of War; strictly use a **Shader-based mask** (SubViewport + ColorRect) for GPU efficiency.
- NEVER process unit AI or pathfinding synchronously for mass groups; strictly offload to **`WorkerThreadPool`** and stagger path updates.
- NEVER use high-poly visual meshes as NavMesh source geometry; strictly use simplified **Collision Shapes** for baking.

### Interaction & Commands
- NEVER forget **Command Queuing** (Shift-Click); strictly store an `Array[Command]` and implement a "Force Move/Attack" bypass.
- NEVER create excessive micromanagement; strictly automate low-level tasks like **auto-aggro range** and auto-return for resource gathering.
- NEVER use exact floating-point equality (==) for grid or timers; strictly use `is_equal_approx()` for deterministic triggers.
- NEVER rely on the visual SceneTree for selection data; strictly maintain a **Typed Selection Set** of `RefCounted` or `Resource` objects for deterministic serialization and netcode.
- NEVER forget **Command Queuing**; strictly implement a **Command Pattern** using serializable `Dictionary` or `JSON` states for save-game and multiplayer playback.
- NEVER forget to **duplicate_deep()** globally shared Resources; otherwise, modifying one unit's data (e.g., stats) affects all.

### Performance & Simulation
- NEVER render thousands of units using separate `MeshInstance3D` nodes; strictly use **`MultiMeshInstance`** with **`INSTANCE_CUSTOM`** data to drive unique GPU-side state animations (walking/attacking/color).
- NEVER calculate transforms for mass units on the main thread; strictly use **`WorkerThreadPool`** to push buffers to `RenderingServer.multimesh_set_buffer()`.
- NEVER update every unit's navigation path in the same frame; strictly use random timers to **stagger updates**.
- NEVER use standard Strings for high-frequency AI state identifiers; strictly use **StringName** (&"harvesting") for pointer-speed comparisons.
- NEVER allow simulation coordinates to exceed 8192 units without float-precision management; strictly use world-origin shifts.
- NEVER use `CSGShape3D` for building placement ghosts; strictly use optimized static `ArrayMesh` geometry.

---

## 🛠 Expert Components (scripts/)

> **MANDATORY**: Read the script for the workflow you are implementing — do not re-inline selection/fog recipes in the agent body.

### Selection / commands
- [selection_manager_marquee_2d.gd](scripts/selection_manager_marquee_2d.gd) — **MANDATORY** for 2D drag-box, filter, shift-add.
- [selection_manager_raycast_3d.gd](scripts/selection_manager_raycast_3d.gd) — **MANDATORY** for 3D PhysicsServer picks.
- [rts_selection_overlay.gd](scripts/rts_selection_overlay.gd) — Selection visuals / box overlay.
- [rts_group_commander.gd](scripts/rts_group_commander.gd) — SceneTree group broadcast for mass orders.
- [rts_targeting_logic.gd](scripts/rts_targeting_logic.gd) — Distance-squared enemy filtering.

### Units / navigation / army
- [rts_unit.gd](scripts/rts_unit.gd) — **MANDATORY** unit controller (states + NavigationAgent).
- [crowd_navigation_unit.gd](scripts/crowd_navigation_unit.gd) — RVO / crowd agent wiring.
- [rts_path_query_pool.gd](scripts/rts_path_query_pool.gd) — Pooled Navigation path queries.
- [navigation_mask_helper.gd](scripts/navigation_mask_helper.gd) — Nav layers / avoidance bitmasks.
- [rts_army_manager.gd](scripts/rts_army_manager.gd) — WorkerThreadPool army AI batches.
- [rts_unit_stat_duplicator.gd](scripts/rts_unit_stat_duplicator.gd) — `duplicate_deep()` isolation for unit Resources.

### Economy / build / fog / ghosts
- [global_economy_manager.gd](scripts/global_economy_manager.gd) — Gather/spend bank Autoload pattern.
- [building_grid_astar.gd](scripts/building_grid_astar.gd) — Grid placement pathing.
- [fog_of_war_tile_mask.gd](scripts/fog_of_war_tile_mask.gd) — **MANDATORY** TileMapLayer fog clear (2D/grid).
- [rendering_ghost_spawner.gd](scripts/rendering_ghost_spawner.gd) — Placement ghosts via RenderingServer RIDs.
- [rts_formation_manager.gd](scripts/rts_formation_manager.gd) — Center-of-mass group path + per-unit formation offsets.
- [rts_massive_unit_renderer.gd](scripts/rts_massive_unit_renderer.gd) — MultiMeshInstance3D army renderer synced from unit transforms.

---

## Core Loop
1. **Gather**: Units collect resources (Gold, Wood, etc.).
2. **Build**: Construct base buildings to unlock tech/units.
3. **Train**: Produce an army of diverse units.
4. **Command**: Micromanage units in real-time battles.
5. **Expand**: Secure map control and resources.

## Skill Chain

| Phase | Skills | Purpose |
|-------|--------|---------|
| 1. Controls | `godot-input-handling`, `godot-camera-systems` | Selection box, camera pan/zoom/edge-scroll |
| 2. Units | `godot-navigation-pathfinding`, `godot-state-machine-advanced` | Pathfinding, RVO avoidance, Idle/Move/Attack |
| 3. Systems | `godot-shaders-basics`, `godot-tilemap-mastery`, `godot-economy-system` | Fog masks / TileMap fog, gather-spend ledger |
| 4. AI | `godot-ai-navigation`, `godot-autoload-architecture` | Enemy commander routing + army/economy Autoloads |
| 5. Polish | `godot-ui-containers`, `godot-particles` | Strategic UI chrome, battle feedback |
| 6. Balance | `godot-monte-carlo-balancer` | Build-order policies vs extracted AI orders |

## Decision Tree: NavigationAgent+RVO vs MultiMesh+server sim

| Active units (order of magnitude) | Simulation / pathing | Rendering | Load |
|-----------------------------------|----------------------|-----------|------|
| < ~80 | Per-unit `NavigationAgent2D/3D` + RVO; `set_velocity` → `velocity_computed` | MeshInstance / Sprite nodes OK | **MANDATORY** `rts_unit.gd`, `crowd_navigation_unit.gd` |
| ~80–400 | Stagger path queries; RVO only while moving; static → `NavigationObstacle`; central commander | Still node visuals; pool path queries | + `rts_path_query_pool.gd`, `rts_army_manager.gd`, Batch 09 COM formation |
| > ~400 / thousands | **Server sim**: logical transforms on WorkerThreadPool; few NavigationServer map queries (COM / squads), not one agent per soldier | **`MultiMeshInstance`** + `INSTANCE_CUSTOM`; push buffers off main thread | `rts_army_manager.gd` + MultiMesh path in Batch 09; **Do NOT Load** per-unit `_process` agents |

**Rule**: Keep NavigationAgent+RVO while units need individual collision avoidance and micromanage feel. Switch to MultiMesh + server-side transforms when draw-call/node cost dominates — path as squads, not as thousands of agents.

## Architecture Overview

### 1. Selection Manager
**MANDATORY**: [selection_manager_marquee_2d.gd](scripts/selection_manager_marquee_2d.gd) (2D) or [selection_manager_raycast_3d.gd](scripts/selection_manager_raycast_3d.gd) (3D). Maintain a **typed selection set** (not SceneTree-only) for netcode/save. Overlay: [rts_selection_overlay.gd](scripts/rts_selection_overlay.gd).

### 2. Unit Controller (State Machine)
**MANDATORY**: [rts_unit.gd](scripts/rts_unit.gd) for Idle/Move/Attack/Hold + NavigationAgent. Deep state graphs → `godot-state-machine-advanced`. Always `duplicate_deep()` shared stat Resources ([rts_unit_stat_duplicator.gd](scripts/rts_unit_stat_duplicator.gd)).

### 3. Group Movement & Formations
Avoid clumping on one click target: compute **center of mass**, apply **relative offsets**, issue per-unit destinations. For hundreds of units, use **one** NavigationServer path for the COM (Batch 09) plus [rts_group_commander.gd](scripts/rts_group_commander.gd) / [rts_path_query_pool.gd](scripts/rts_path_query_pool.gd).

### 4. Fog of War
**MANDATORY** for tile/grid fog: [fog_of_war_tile_mask.gd](scripts/fog_of_war_tile_mask.gd). SubViewport mask + shader overlay is valid for soft vision — implement via docs (`Using Viewports`) + `godot-shaders-basics`; **Do NOT** paste long fog shaders into this skill body when the tile-mask script covers the grid path.

## Key Mechanics Implementation

### Command Queue
Shift-click chains: store `Array` of serializable commands; pop on finish; draw queued path lines. Pair with selection scripts' issue-command hooks.

### Resource Gathering
`ResourceNode` → work timer → `DropoffPoint` → bank update. Wire bank through [global_economy_manager.gd](scripts/global_economy_manager.gd) / `godot-economy-system`.

## Common Pitfalls

1. **Pathfinding jitter** — Enable RVO; call `set_velocity` + move on `velocity_computed`; stagger group path queries.
2. **Too much micro** — Auto-aggro / auto-return gather; command queue for force-move/attack.
3. **Node explosion** — Past a few hundred units, follow the decision tree (MultiMesh + army manager), not per-unit `_process`.

## Godot-Specific Tips

* **Avoidance**: `NavigationAgent*` RVO requires `set_velocity()` + `velocity_computed` for the actual move.
* **Server architecture**: Central `UnitManager` / [rts_army_manager.gd](scripts/rts_army_manager.gd) for 100+ units.
* **Groups**: `Units`, `Buildings`, `Resources` for selection filters.

---

## 🚀 Elite Technical Implementations (Batch 09)

### 1. Center-of-Mass Formation Movement
For large selections, one NavigationServer path from COM → target, then offset each unit (see decision tree). Keep the algorithm in project code or formation helpers; pair with [rts_path_query_pool.gd](scripts/rts_path_query_pool.gd) so path objects are pooled.

```gdscript
# Sketch only — prefer pooled queries from rts_path_query_pool.gd
static func move_group_to_target(units: Array, target: Vector3, map_rid: RID) -> void:
    if units.is_empty():
        return
    var com := Vector3.ZERO
    for u in units:
        com += u.global_position
    com /= units.size()
    var path: PackedVector3Array = NavigationServer3D.map_get_path(map_rid, com, target, true)
    if path.is_empty():
        return
    var dest: Vector3 = path[path.size() - 1]
    for u in units:
        u.set_movement_target(dest + (u.global_position - com))
```

### 2. MultiMesh armies (when decision tree says so)
Pre-allocate `instance_count`, drive `visible_instance_count`, push transforms (optionally via WorkerThreadPool → `RenderingServer.multimesh_set_buffer`). No per-soldier `MeshInstance3D`. See Official Documentation → Using MultiMesh.

### 3. Fog — script first
Prefer [fog_of_war_tile_mask.gd](scripts/fog_of_war_tile_mask.gd). SubViewport vision masks: docs + `godot-shaders-basics` (do not duplicate long shader bodies here).

> **MANDATORY** for depth beyond decision trees and script catalog: [rts-mass-army-deep.md](references/rts-mass-army-deep.md). **Do NOT Load** on first-pass wiring — use bundled `scripts/` first.

## Reference

> Progressive disclosure: open Official Documentation links only when researching a specific API;
> load Related Skills when routing work to a peer domain — do not preload the whole lattice.

### Official Documentation
- [Navigation (tutorial index)](https://docs.godotengine.org/en/stable/tutorials/navigation/index.html) — Entry map for agents, servers, meshes, layers, and obstacles before wiring army movement.
- [Using NavigationAgents](https://docs.godotengine.org/en/stable/tutorials/navigation/navigation_using_navigationagents.html) — `set_velocity` / `velocity_computed` RVO loop that stops crowd jitter and stuck IDLE timeouts.
- [Using NavigationServers](https://docs.godotengine.org/en/stable/tutorials/navigation/navigation_using_navigationservers.html) — Direct map path queries for center-of-mass formation moves without per-unit agent spam.
- [Using navigation path query objects](https://docs.godotengine.org/en/stable/tutorials/navigation/navigation_using_navigationpathqueryobjects.html) — Pooled `NavigationPathQueryParameters*` patterns for mass move orders without heap churn.
- [Optimizing navigation performance](https://docs.godotengine.org/en/stable/tutorials/navigation/navigation_optimizing_performance.html) — Staggered queries, avoidance budgets, and obstacle swaps when hundreds of units path each tick.
- [Using MultiMesh](https://docs.godotengine.org/en/stable/tutorials/performance/using_multimesh.html) — GPU instance buffers for thousands of units instead of one `MeshInstance` per soldier.
- [Using multiple threads](https://docs.godotengine.org/en/stable/tutorials/performance/using_multiple_threads.html) — `WorkerThreadPool` contracts for army AI batches off the main thread.
- [Ray-casting](https://docs.godotengine.org/en/stable/tutorials/physics/ray-casting.html) — Direct space-state picks for 3D selection and ground click targeting.
- [Using Viewports](https://docs.godotengine.org/en/stable/tutorials/rendering/viewports.html) — SubViewport vision masks that feed fog-of-war shaders without CPU tile floods.
- [Mouse and input coordinates](https://docs.godotengine.org/en/stable/tutorials/inputs/mouse_and_input_coordinates.html) — Screen-to-world mapping for marquee boxes, unproject selection, and shift-queued orders.
- [AStarGrid2D](https://docs.godotengine.org/en/stable/classes/class_astargrid2d.html) — Fast grid pathing for building footprints and base placement checks.
- [Resources](https://docs.godotengine.org/en/stable/tutorials/scripting/resources.html) — Why unit stats must `duplicate(true)` so health/armor never mutate a shared template.

### Related Skills

#### Prerequisites
- [godot-project-foundations](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-project-foundations/SKILL.md) — Physics ticks, navigation/avoidance project settings, and input map actions before selection and pathing stay deterministic.
- [godot-input-handling](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-input-handling/SKILL.md) — Mouse buttons, shift-modifiers, and physics-step sampling that drive marquee select and command queuing.
- [godot-navigation-pathfinding](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-navigation-pathfinding/SKILL.md) — NavigationAgent RVO, maps, layers, and query-object pools this genre's army movement builds on.

#### Complements
- [godot-camera-systems](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-camera-systems/SKILL.md) — RTS pan/zoom/edge-scroll framing so selection and orders stay readable at strategic scale.
- [godot-raycasting-queries](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-raycasting-queries/SKILL.md) — PhysicsServer ray/shape recipes for 3D picks under heavy unit counts.
- [godot-state-machine-advanced](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-state-machine-advanced/SKILL.md) — Idle/Move/Attack/Hold command states and queue transitions per unit without spaghetti flags.
- [godot-shaders-basics](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-shaders-basics/SKILL.md) — CanvasItem/spatial mask shaders that sample SubViewport fog textures.
- [godot-autoload-architecture](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-autoload-architecture/SKILL.md) — Global economy and army managers as Autoloads with clear boot order.
- [godot-economy-system](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-economy-system/SKILL.md) — Gather/spend ledgers and cost dictionaries the RTS bank Autoload should reuse.
- [godot-signal-architecture](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-signal-architecture/SKILL.md) — Group broadcast and command buses so commanders never hard-iterate every unit node.

#### Downstream / consumers
- [godot-monte-carlo-balancer](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-monte-carlo-balancer/SKILL.md) — Build-order policies, unit cost curves, and AI opponent strength — simulate win% instead of gut-tuning gather rates.
- [godot-performance-optimization](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-performance-optimization/SKILL.md) — Escalate here when MultiMesh buffers, avoidance, or WorkerThreadPool still dominate the profiler.
- [godot-combat-system](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-combat-system/SKILL.md) — Hit/hurt and targeting contracts once move/attack commands need damage resolution.

#### Master
- [godot-master](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-master/SKILL.md) — Library router and mirrored module entry; open when discovering which Domain Skill owns a cross-cutting RTS concern.

More from thedivergentai/GD-Agentic-Skills

SkillDescription
godot-2d-animationExpert patterns for 2D animation in Godot using AnimatedSprite2D and skeletal cutout rigs. Use when implementing sprite frame animations, procedural animation (squash/stretch), cutout bone hierarchies, or frame-perfect timing systems. Trigger keywords: AnimatedSprite2D, SpriteFrames, animation_finished, animation_looped, frame_changed, frame_progress, set_frame_and_progress, cutout animation, skeletal 2D, Bone2D, procedural animation, animation state machine, advance(0).
godot-2d-physicsExpert patterns for Godot 2D physics including collision layers/masks, Area2D triggers, raycasting, and PhysicsDirectSpaceState2D queries. Use when implementing collision detection, trigger zones, line-of-sight systems, or manual physics queries. Trigger keywords: CollisionShape2D, CollisionPolygon2D, collision_layer, collision_mask, set_collision_layer_value, set_collision_mask_value, Area2D, body_entered, body_exited, RayCast2D, force_raycast_update, PhysicsPointQueryParameters2D, PhysicsShapeQueryParameters2D, direct_space_state, move_and_collide, move_and_slide.
godot-3d-lightingExpert patterns for Godot 3D lighting including DirectionalLight3D shadow cascades, OmniLight3D attenuation, SpotLight3D projectors, VoxelGI vs SDFGI, and LightmapGI baking. Use when implementing realistic 3D lighting, shadow optimization, global illumination, or light probes. Trigger keywords: DirectionalLight3D, OmniLight3D, SpotLight3D, shadow_enabled, directional_shadow_mode, directional_shadow_split, omni_range, omni_attenuation, spot_range, spot_angle, VoxelGI, SDFGI, LightmapGI, ReflectionProbe, Environment, WorldEnvironment.
godot-3d-materialsExpert patterns for Godot 3D PBR materials using StandardMaterial3D including albedo, metallic/roughness workflows, normal maps, ORM texture packing, transparency modes, and shader conversion. Use when creating realistic 3D surfaces, PBR workflows, or material optimization. Trigger keywords: StandardMaterial3D, BaseMaterial3D, albedo_texture, metallic, metallic_texture, roughness, roughness_texture, normal_texture, normal_enabled, orm_texture, transparency, alpha_scissor, alpha_hash, cull_mode, ShaderMaterial, shader parameters.
godot-3d-world-buildingExpert patterns for 3D level design using GridMap with MeshLibrary, CSG constructive solid geometry, occlusion, and runtime GridMap builders. Use when building 3D levels, modular tilesets, or BSP-style geometry. For sky/fog/Environment recipes, route to godot-3d-lighting. Trigger keywords: GridMap, MeshLibrary, set_cell_item, get_cell_item, map_to_local, local_to_map, CSGCombiner3D, CSGBox3D, CSGSphere3D, CSGPolygon3D, OccluderInstance3D, bake CSG.
godot-ability-systemExpert patterns for RPG/action ability systems including cooldown strategies, combo systems, ability chaining, skill trees with prerequisites, upgrade paths, and resource management. Use when implementing unlockable abilities, character progression, or complex skill systems. Trigger keywords: PlayerAbility, AbilityManager, cooldown, SkillTree, SkillNode, prerequisites, can_use, execute, ComboSystem, ability_chain, global_cooldown, charge_system, upgrade_path.
godot-adapt-2d-to-3dExpert patterns for migrating 2D games to 3D including node type conversions, camera systems (third-person, first-person, orbit), physics layer migration, sprite-to-model art pipeline, and control scheme adaptations. Use when porting 2D projects to 3D or adding 3D elements. Trigger keywords: CharacterBody2D to CharacterBody3D, Area2D to Area3D, Camera2D to Camera3D, Vector2 to Vector3, collision_layer migration, sprite to MeshInstance3D, 2D to 3D conversion.
godot-adapt-3d-to-2dExpert patterns for simplifying 3D games to 2D including dimension reduction strategies, 2.5D fake-depth, isometric ports, camera flattening, physics conversion, 3D-to-sprite art pipeline, and control simplification. Use when porting 3D to 2D, building 2.5D / isometric / fake-depth gameplay, creating 2D versions for mobile, or prototyping. Trigger keywords: CharacterBody3D to CharacterBody2D, Camera3D to Camera2D, Vector3 to Vector2, flatten Z-axis, 2.5D, isometric, fake depth, Y-sort, simulated Z, orthogonal projection, 3D to sprite conversion, performance optimization.
godot-adapt-desktop-to-mobileExpert patterns for porting desktop games to mobile including touch control schemes (virtual joystick, gesture detection), UI scaling for small screens, performance optimization for mobile GPUs, battery life management, and platform-specific features. Use when creating mobile ports or cross-platform mobile builds. Trigger keywords: TouchScreenButton, virtual_joystick, gesture_detector, InputEventScreenTouch, InputEventScreenDrag, mobile_optimization, battery_saving, adaptive_performance, MOBILE_ENABLED.
godot-adapt-mobile-to-desktopExpert patterns for scaling mobile games to desktop including mouse/keyboard controls, increased resolution and graphical fidelity, expanded UI layouts, settings menus, window management, and platform-specific features. Use when creating desktop ports or cross-platform releases. Trigger keywords: mouse_controls, keyboard_shortcuts, resolution_scaling, graphics_settings, fullscreen_toggle, window_modes, Steam_integration, desktop_optimization.