Installs into .claude/skills of the current project.
Are you the author of Debug Issue?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/n24q02m-debug-issue)
---
name: debug-issue
description: Systematic Godot debugging decision trees for physics, signals, rendering, navigation, and input issues
argument-hint: "[symptom description]"
---
# Debug Issue
Systematic debugging using domain-specific decision trees. Start by identifying the symptom category, then follow the corresponding tree.
## Category Detection
Map user's symptom to the right tree:
| Symptom keywords | Category |
|---|---|
| "pass through", "no collision", "overlap", "stuck", "slides off" | Physics |
| "signal not firing", "not connected", "callback not called" | Signals |
| "invisible", "not showing", "behind", "flickering", "wrong color" | Rendering |
| "not moving to target", "path wrong", "stuck on nav", "no path" | Navigation |
| "key not working", "input ignored", "wrong button", "double input" | Input |
## Physics Decision Tree
Check in this order -- each step is the most common cause at that point:
1. **Collision layer/mask mismatch** (most common):
- Check defined layer names: `physics(action="layers")`
- Check node properties:
```
nodes(action="get_property", scene_path="<scene>.tscn", name="<body>", property="collision_layer")
nodes(action="get_property", scene_path="<scene>.tscn", name="<body>", property="collision_mask")
```
- Rule: Object A detects Object B only if A's `collision_mask` has a bit that matches B's `collision_layer`. Both must be set correctly.
2. **Missing CollisionShape2D/3D**:
- Inspect the scene tree: `scenes(action="info", scene_path="<scene>.tscn")`
- Verify every physics body and Area has a CollisionShape child. A body without a shape = invisible to physics.
3. **Wrong body type**:
- `StaticBody2D`: immovable (walls, floors)
- `CharacterBody2D`: player/NPC movement via `move_and_slide()`
- `RigidBody2D`: physics-driven (projectiles, debris)
- Common mistake: using `RigidBody2D` for a player character, then fighting the physics engine
4. **Script velocity issues**:
- Read the script: `scripts(action="read", script_path="res://scripts/<name>.gd")`
- Check if `velocity` is being set before `move_and_slide()`
- Check if gravity is applied in `_physics_process` (not `_process`)
- Check if `delta` is used for frame-independent movement
## Signals Decision Tree
1. **Connection exists?**
- List all connections: `signals(action="list", scene_path="<scene>.tscn")`
- Missing connection = signal silently does nothing
2. **Signature match?**
- Signal definition parameters must match handler function parameters
- `signal health_changed(new_hp: int)` requires handler `func _on_health_changed(new_hp: int)`
- Extra or missing parameters = Godot error at runtime
3. **Signal emitted?**
- Add `print("signal emitted")` before `emit_signal()` / `signal.emit()`
- If not printed, the emit call is never reached (logic bug)
4. **Callable valid?**
- If connected via code: target node must exist when `connect()` runs
- If target is freed, signal emits to invalid callable = error
## Rendering Decision Tree
1. **Visibility**:
- `visible` property = false? Check node and ALL parents (parent invisible = children invisible)
- `modulate.a` = 0? (fully transparent)
2. **Z-index**:
- Lower z-index renders behind higher z-index
- `z_as_relative` = true means z_index is relative to parent
- Sprite behind a TileMapLayer? Check z_index values on both
3. **Material/shader**:
- CanvasItemMaterial or ShaderMaterial overriding appearance?
- Shader compilation errors make object invisible (check Output panel)
4. **Viewport issues**:
- SubViewport not updating? Check `render_target_update_mode`
- Camera2D not active? Only one Camera2D should have `enabled = true` per viewport
## Navigation Decision Tree
1. **NavigationRegion setup**:
- `NavigationRegion2D`/`3D` must exist in scene
- Must have a `NavigationPolygon`/`NavigationMesh` resource assigned
2. **Navigation mesh baked?**
- Mesh must be baked (either in editor or via `bake_navigation_mesh()`)
- Unbaked mesh = no paths available
3. **NavigationAgent config**:
- `path_desired_distance`: how close before moving to next path point
- `target_desired_distance`: how close to target before stopping
- Values too small = agent oscillates; too large = imprecise
4. **Path calculation**:
- Call `NavigationAgent.set_target_position()` then check `get_next_path_position()`
- If returns current position, no valid path exists (check mesh coverage)
## Input Decision Tree
1. **Input Map**:
- List actions: `input_map(action="list")`
- Check `project.godot` for `[input]` section
2. **Action name match**:
- `Input.is_action_pressed("jump")` -- exact string match required
- Typo in action name = silently returns false (no error!)
3. **Event processing**:
- `_input()` vs `_unhandled_input()` -- if another node consumes the event, `_unhandled_input` never fires
- `set_process_input(false)` disables `_input()` on that node
4. **Conflicts**:
- Two actions on same key = both fire
- UI elements (Button, LineEdit) consume input events before game nodes
## Diagnostic Steps
For any category:
1. **Inspect the scene tree**: `scenes(action="info", scene_path="<scene>.tscn")`
2. **Read relevant scripts**: `scripts(action="read", script_path="res://scripts/<name>.gd")`
3. **Check properties**: `nodes(action="get_property", scene_path="<scene>.tscn", name="<node_path>", property="<name>")`
4. **Run the scene**: `project(action="run", scene_path="<scene>.tscn")` and check output for errors
5. **Report findings**: present root cause and specific fix (property change, missing node, script edit)
## When to Use
- Any "it doesn't work" debugging scenario in Godot
- Systematic elimination when the cause is not obvious
- Verifying correct setup of physics, signals, rendering, navigation, or input