Dependency Injection
Use when managing dependencies between systems, autoloads, service locators, @export...
Install
npx skills add jame581/GodotPrompter --skill dependency-injection -g -a claude-code -y- Repository
- jame581/GodotPrompter914
- Category
- Engineering
- Updated
- 3d ago
- License
- MIT
- Context cost
- Mediumabout 2,781 tokens
- Runs scripts
- No, instructions only
What it does
Use when managing dependencies between systems, autoloads, service locators, @export injection, and scene injection patterns
Dependency Injection in Godot 4.3+
Patterns for wiring dependencies between systems so nodes stay loosely coupled, swappable, and testable. All examples target Godot 4.3+ with no deprecated APIs.
Related skills: godot-testing for test-friendly architecture, event-bus for signal-based decoupling, godot-project-setup for autoload registration.
1. The Problem
Tight coupling makes code hard to test, extend, and swap. The most common form in Godot is reaching directly into a global autoload from everywhere in the codebase.
# BAD, tight coupling via direct autoload access scattered everywhere
# player.gd
func take_damage(amount: int) -> void:
health -= amount
AudioManager.play_sfx("hurt") # hard dependency on AudioManager
UIManager.update_health_bar(health) # hard dependency on UIManager
if health <= 0:
GameState.record_death() # hard dependency on GameState
# enemy.gd
func attack() -> void:
AudioManager.play_sfx("attack") # same AudioManager dependency again
// BAD, tight coupling via direct autoload / global access scattered everywhere
// Player.cs
public partial class Player : CharacterBody3D
{
private int _health = 100;
public void TakeDamage(int amount)
{
_health -= amount;
GetNode<AudioManager>("/root/AudioManager").PlaySfx("hurt"); // hard dependency
GetNode<UIManager>("/root/UIManager").UpdateHealthBar(_health); // hard dependency
if (_health <= 0)
GetNode<GameState>("/root/GameState").RecordDeath(); // hard dependency
}
}
// Enemy.cs
public partial class Enemy : CharacterBody3D
{
public void Attack()
{
GetNode<AudioManager>("/root/AudioManager").PlaySfx("attack"); // same dependency again
}
}
Problems with this approach:
