Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Godot Engine integration skill for GDScript/C# development, scene composition, node management, and editor automation. Enables LLMs to interact with Godot Editor through MCP servers for asset manipulation, script generation, and automated workflows.
.claude/skills/a5c-ai-godot-development/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 73% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 154% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 130% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 83% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 153% | 0% |
Comprehensive Godot Engine development integration for AI-assisted game creation, editor automation, and project management.
This skill provides capabilities for interacting with Godot projects, including GDScript and C# development, scene manipulation, node management, and export automation. It leverages the Godot MCP ecosystem for direct editor integration when available.
For direct Godot Editor integration:
json{ "mcpServers": { "godot": { "command": "npx", "args": ["-y", "godot-mcp"], "env": { "GODOT_PROJECT_PATH": "/path/to/godot/project" } } } }
Alternative MCP servers:
Godot-MCP (ee0pdt) - Comprehensive editor integrationgodot-mcp (Coding-Solo) - Project launch and debuggingGDAI MCP Server - Script fixing with screenshotsgdscriptextends CharacterBody2D class_name PlayerController ## Movement speed in pixels per second @export var move_speed: float = 200.0 ## Jump velocity @export var jump_velocity: float = -400.0 ## Gravity from project settings var gravity: float = ProjectSettings.get_setting("physics/2d/default_gravity") ## Emitted when the player takes damage signal damage_taken(amount: int) ## Emitted when the player dies signal died var _is_alive: bool = true func _physics_process(delta: float) -> void: if not _is_alive: return _apply_gravity(delta) _handle_jump() _handle_movement() move_and_slide() func _apply_gravity(delta: float) -> void: if not is_on_floor(): velocity.y += gravity * delta func _handle_jump() -> void: if Input.is_action_just_pressed("jump") and is_on_floor(): velocity.y = jump_velocity func _handle_movement() -> void: var direction := Input.get_axis("move_left", "move_right") if direction: velocity.x = direction * move_speed else: velocity.x = move_toward(velocity.x, 0, move_speed) func take_damage(amount: int) -> void: damage_taken.emit(amount) func die() -> void: _is_alive = false died.emit()
gdscript@tool extends Resource class_name EnemyData ## Display name of the enemy @export var enemy_name: String = "Enemy" ## Enemy icon for UI @export var icon: Texture2D ## Maximum health points @export var max_health: int = 100 ## Movement speed @export var move_speed: float = 100.0 @export_group("Combat") ## Damage dealt per attack @export var attack_damage: int = 10 ## Range of attack in pixels @export var attack_range: float = 50.0 ## Cooldown between attacks @export var attack_cooldown: float = 1.0 @export_group("Rewards") ## Experience points awarded on death @export var exp_reward: int = 50 ## Items that can drop @export var loot_table: Array[PackedScene] ## Get damage per second potential func get_dps() -> float: return attack_damage / attack_cooldown
gdscriptextends Node class_name StateMachine ## Emitted when state changes signal state_changed(old_state: State, new_state: State) @export var initial_state: State var current_state: State var states: Dictionary = {} func _ready() -> void: for child in get_children(): if child is State: states[child.name.to_lower()] = child child.state_machine = self if initial_state: current_state = initial_state current_state.enter() func _process(delta: float) -> void: if current_state: current_state.update(delta) func _physics_process(delta: float) -> void: if current_state: current_state.physics_update(delta) func _unhandled_input(event: InputEvent) -> void: if current_state: current_state.handle_input(event) func transition_to(state_name: String) -> void: var new_state: State = states.get(state_name.to_lower()) if new_state == null: push_warning("State '%s' not found" % state_name) return if current_state: current_state.exit() var old_state := current_state current_state = new_state current_state.enter() state_changed.emit(old_state, new_state)
csharpusing Godot; using System; public partial class PlayerController : CharacterBody2D { [Export] public float MoveSpeed { get; set; } = 200.0f; [Export] public float JumpVelocity { get; set; } = -400.0f; [Signal] public delegate void DamageTakenEventHandler(int amount); [Signal] public delegate void DiedEventHandler(); private float _gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle(); private bool _isAlive = true; public override void _PhysicsProcess(double delta) { if (!_isAlive) return; Vector2 velocity = Velocity; // Apply gravity if (!IsOnFloor()) { velocity.Y += _gravity * (float)delta; } // Handle jump if (Input.IsActionJustPressed("jump") && IsOnFloor()) { velocity.Y = JumpVelocity; } // Handle movement float direction = Input.GetAxis("move_left", "move_right"); velocity.X = direction != 0 ? direction * MoveSpeed : Mathf.MoveToward(velocity.X, 0, MoveSpeed); Velocity = velocity; MoveAndSlide(); } public void TakeDamage(int amount) { EmitSignal(SignalName.DamageTaken, amount); } public void Die() { _isAlive = false; EmitSignal(SignalName.Died); } }
javascriptconst godotScriptTask = defineTask({ name: 'godot-script-generation', description: 'Generate Godot script', inputs: { language: { type: 'string', required: true }, // gdscript, csharp baseClass: { type: 'string', required: true }, className: { type: 'string', required: true }, features: { type: 'array', required: true }, outputPath: { type: 'string', required: true } }, outputs: { scriptPath: { type: 'string' }, success: { type: 'boolean' } }, async run(inputs, taskCtx) { return { kind: 'skill', title: `Generate Godot script: ${inputs.className}`, skill: { name: 'godot-development', context: { operation: 'generate_script', language: inputs.language, baseClass: inputs.baseClass, className: inputs.className, features: inputs.features, outputPath: inputs.outputPath } }, io: { inputJsonPath: `tasks/${taskCtx.effectId}/input.json`, outputJsonPath: `tasks/${taskCtx.effectId}/result.json` } }; } });
| Tool | Description | |------|-------------| | godot_create_node | Create node in scene | | godot_modify_node | Modify node properties | | godot_create_script | Generate and attach script | | godot_run_project | Launch project in editor | | godot_run_scene | Run specific scene | | godot_export | Export for target platform | | godot_get_scene_tree | Query scene structure | | godot_read_errors | Get editor error output | | godot_screenshot | Capture viewport screenshot |
json{ "mcpServers": { "godot": { "command": "python", "args": ["-m", "godot_mcp"], "env": { "GODOT_PROJECT_PATH": "/path/to/godot/project", "GODOT_EXECUTABLE": "/path/to/godot" } } } }
| Platform | Key Considerations | |----------|-------------------| | PC/Mac/Linux | Full feature support | | Mobile | Touch input, reduced shaders, export templates | | Web | No threading, WASM limitations | | Console | Requires third-party publishing partners |
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 13,154 | 30,635 | +133% | 1 | 1 | 0% | 2,719 | 4,694 | +73% | 0 | 0 | — |
case-02 | pass→pass | 11,237 | 12,023 | +7% | 1 | 1 | 0% | 1,827 | 4,882 | +167% | 0 | 0 | — |
case-03 | fail→pass | 8,569 | 8,290 | -3% | 1 | 1 | 0% | 1,737 | 4,407 | +154% | 0 | 0 | — |
case-04 | fail→fail | 23,062 | 29,101 | +26% | 1 | 1 | 0% | 3,668 | 7,592 | +107% | 0 | 0 | — |
case-05 | pass→pass | 9,051 | 9,816 | +8% | 1 | 1 | 0% | 1,842 | 4,861 | +164% | 0 | 0 | — |
case-06 | fail→pass | 20,431 | 4,336 | -79% | 1 | 1 | 0% | 1,486 | 3,413 | +130% | 0 | 0 | — |
case-07 | fail→pass | 13,638 | 6,212 | -54% | 1 | 1 | 0% | 2,204 | 4,031 | +83% | 0 | 0 | — |
case-08 | pass→pass | 11,071 | 14,622 | +32% | 1 | 1 | 0% | 1,885 | 4,862 | +158% | 0 | 0 | — |
case-09 | fail→pass | 8,538 | 1,758 | -79% | 1 | 1 | 0% | 1,207 | 3,059 | +153% | 0 | 0 | — |
case-10 | fail→pass | 11,795 | 3,200 | -73% | 1 | 1 | 0% | 1,628 | 3,332 | +105% | 0 | 0 | — |
case-11 | fail→pass | 13,617 | 2,357 | -83% | 1 | 1 | 0% | 1,906 | 3,135 | +64% | 0 | 0 | — |
case-12 | pass→pass | 18,617 | 19,137 | +3% | 1 | 1 | 0% | 3,059 | 5,549 | +81% | 0 | 0 | — |
case-13 | pass→pass | 21,828 | 21,163 | -3% | 1 | 1 | 0% | 3,354 | 5,839 | +74% | 0 | 0 | — |
case-14 | pass→pass | 11,917 | 11,725 | -2% | 1 | 1 | 0% | 2,181 | 4,815 | +121% | 0 | 0 | — |
case-15 | pass→pass | 10,575 | 8,899 | -16% | 1 | 1 | 0% | 1,715 | 4,022 | +135% | 0 | 0 | — |
case-16 | pass→pass | 4,879 | 4,603 | -6% | 1 | 1 | 0% | 654 | 3,510 | +437% | 0 | 0 | — |
case-17 | pass→pass | 11,585 | 9,058 | -22% | 1 | 1 | 0% | 1,634 | 4,308 | +164% | 0 | 0 | — |
case-18 | pass→pass | 6,451 | 4,749 | -26% | 1 | 1 | 0% | 1,116 | 3,558 | +219% | 0 | 0 | — |
case-19 | pass→pass | 14,039 | 17,522 | +25% | 1 | 1 | 0% | 2,143 | 5,384 | +151% | 0 | 0 | — |
case-20 | pass→pass | 11,325 | 8,761 | -23% | 1 | 1 | 0% | 2,036 | 4,345 | +113% | 0 | 0 | — |
case-21 | pass→pass | 11,697 | 6,838 | -42% | 1 | 1 | 0% | 1,770 | 4,104 | +132% | 0 | 0 | — |
case-22 | pass→pass | 8,010 | 10,852 | +35% | 1 | 1 | 0% | 1,187 | 4,400 | +271% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +32 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.