Godot Engine patterns, Node tree architecture, Signals, Resources, and GDScript/C# conventions
Generates Godot Engine code following Node tree architecture, Signals, Resources, and GDScript/C# best practices.
npx claudepluginhub davincidreams/atlas-agent-teamsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Look for: project.godot, .tscn, .tres, .gd, .gdshader, addons/, export_presets.cfg
my_game/
scenes/
player/
player.tscn
player.gd
enemies/
enemy_base.tscn
enemy_base.gd
ui/
hud.tscn
main_menu.tscn
levels/
level_01.tscn
scripts/
autoloads/
game_manager.gd
audio_manager.gd
resources/
weapon_data.gd
utilities/
state_machine.gd
assets/
sprites/
models/
audio/
fonts/
addons/ # Third-party plugins
project.godot
export_presets.cfg
Everything in Godot is a Node. Scenes are reusable node trees:
# player.gd - attached to the root node of player.tscn
extends CharacterBody2D
@export var speed: float = 200.0
@export var jump_velocity: float = -400.0
@onready var animated_sprite = $AnimatedSprite2D
@onready var collision_shape = $CollisionShape2D
@onready var health_component = $HealthComponent
var gravity: float = ProjectSettings.get_setting("physics/2d/default_gravity")
func _ready() -> void:
# Called when node enters scene tree
health_component.health_depleted.connect(_on_health_depleted)
func _physics_process(delta: float) -> void:
# Called every physics frame (fixed timestep)
if not is_on_floor():
velocity.y += gravity * delta
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = jump_velocity
var direction = Input.get_axis("move_left", "move_right")
velocity.x = direction * speed
move_and_slide()
func _process(delta: float) -> void:
# Called every frame (variable timestep)
# Use for visual updates, input that doesn't affect physics
pass
func _on_health_depleted() -> void:
queue_free()
Signals are Godot's observer pattern for decoupled communication:
# Defining custom signals
signal health_changed(new_health: float)
signal died
# Emitting signals
func take_damage(amount: float) -> void:
current_health -= amount
health_changed.emit(current_health)
if current_health <= 0:
died.emit()
# Connecting signals (in code)
func _ready() -> void:
# Connect to child node's signal
$HealthComponent.health_changed.connect(_on_health_changed)
# Connect with bind for extra data
$Button.pressed.connect(_on_button_pressed.bind("confirm"))
# Connecting signals (in editor)
# Use the Node > Signals panel to connect visually
Custom Resources are Godot's equivalent of ScriptableObjects:
# weapon_data.gd
class_name WeaponData
extends Resource
@export var weapon_name: String = ""
@export var damage: int = 10
@export var attack_speed: float = 1.0
@export var range: float = 100.0
@export var projectile_scene: PackedScene
@export var attack_sound: AudioStream
Usage:
# weapon_controller.gd
extends Node2D
@export var weapon_data: WeaponData
func attack() -> void:
var projectile = weapon_data.projectile_scene.instantiate()
projectile.damage = weapon_data.damage
get_tree().current_scene.add_child(projectile)
# state_machine.gd
class_name StateMachine
extends Node
@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.transitioned.connect(_on_state_transitioned)
if initial_state:
initial_state.enter()
current_state = initial_state
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 _on_state_transitioned(state: State, new_state_name: String) -> void:
if state != current_state:
return
var new_state = states.get(new_state_name.to_lower())
if new_state:
current_state.exit()
new_state.enter()
current_state = new_state
# state.gd
class_name State
extends Node
signal transitioned(state: State, new_state_name: String)
func enter() -> void:
pass
func exit() -> void:
pass
func update(delta: float) -> void:
pass
func physics_update(delta: float) -> void:
pass
Register in Project > Project Settings > Autoload:
# game_manager.gd (autoload)
extends Node
signal game_paused
signal game_resumed
var score: int = 0
var is_paused: bool = false
func pause_game() -> void:
is_paused = true
get_tree().paused = true
game_paused.emit()
func resume_game() -> void:
is_paused = false
get_tree().paused = false
game_resumed.emit()
@onready var sprite = $Sprite2Dget_tree().get_nodes_in_group("enemies")create_tween().tween_property(self, "position", target, 0.5)get_node() with long paths - use @onready or signals insteadfind_child() in _process - cache referencesvar items: Array[Item] = []call_deferred()get_tree().reload_current_scene() without cleanupsnake_case for functions and variablesPascalCase for classes and nodesSCREAMING_SNAKE_CASE for constants_private_varfunc attack(target: Enemy) -> int:StringName for frequently compared strings: &"idle"Activates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
This skill should be used when the user wants to "create a skill", "add a skill to plugin", "write a new skill", "improve skill description", "organize skill content", or needs guidance on skill structure, progressive disclosure, or skill development best practices for Claude Code plugins.