# CLAUDE.md - AI Assistant Guidelines for Godot 4 C# Development ## File Creation Guidelines ### Files AI CAN Create/Edit - **`.cs` files** - All C# script files (preferred for game logic) - **`.tscn` files** - Scene files with basic/logical structure - **`.cfg` files** - Configuration files (like .ini format) ### Files AI Should Create WITH CAUTION - **`.gd` files** - Only for EditorScript tools (preferred over C# for editor extensions) - **`.tres` files** - Simple resources CAN be created as text: ``` [gd_resource type="Resource" script_class="Recipe" path="res://scripts/Recipe.cs"] id = "fire_water_steam" ingredients = ["fire", "water"] instability_cost = 20.0 ``` BUT: Complex resources with node references or nested resources are better created in editor ### Files AI Should RARELY Create - **`.json` files** - Only for external data exchange or modding support - Use `.tres` for all game data instead (type-safe, Inspector-editable) - **`.md` files** - Documentation files, only when specifically requested ### Files AI Should NOT Create - **`.import` files** - Godot manages these automatically - **`project.godot`** - Only modify through Project Settings UI - **`.gdshader` files** - Visual shader editing is more efficient - **Binary files** - Images, sounds, models, etc. ## Scene File (.tscn) Guidelines ### AI CAN Generate in .tscn ```tscn # Basic node structure [node name="Player" type="CharacterBody2D"] unique_name_in_owner = true script = ExtResource("1") # Node hierarchy [node name="Sprite2D" type="Sprite2D" parent="."] # Signal connections [connection signal="pressed" from="Button" to="." method="_on_button_pressed"] # Simple collision shapes [sub_resource type="RectangleShape2D" id="1"] size = Vector2(32, 32) ``` ### Human Handles in Editor - Sprite textures and animations - Precise collision shape adjustments - Animation tracks in AnimationPlayer - Particle system parameters - Complex UI layouts with exact positioning - Tilemap painting - Navigation mesh baking - Audio bus assignments ## Division of Labor ### AI Handles (Logic & Structure) - Game logic and systems in C# - Node hierarchy structure - Script functionality - Basic scene composition - Export variable definitions - Signal method implementations - Resource class definitions ### Human Handles (Visual & Feel) - Sprite assignment and animation - Collision shape fine-tuning - Visual effects and particles - UI precise positioning - Audio integration - Testing game feel - Input mapping ## C# Code Best Practices ### Node References ```csharp // GOOD - Unique names (set in .tscn with unique_name_in_owner = true) private Node player; public override void _Ready() { player = GetNode("%Player"); } // GOOD - Relative paths for direct children private Sprite2D sprite; public override void _Ready() { sprite = GetNode("Sprite2D"); } // AVOID - Fragile absolute paths var player = GetNode("/root/Main/World/Player"); ``` ### Signals ```csharp // For static connections (nodes in same scene): // AI provides the method, human connects in editor OR AI adds to .tscn private void _OnButtonPressed() { GD.Print("Button pressed!"); } // For dynamic connections (runtime created nodes): // AI writes the connection code public override void _Ready() { if (!enemy.Died.IsConnected(Callable.From(_OnEnemyDied))) { enemy.Died.Connect(Callable.From(_OnEnemyDied)); } } ``` ### Export Variables ```csharp // AI defines them with sensible defaults [Export] public float MoveSpeed { get; set; } = 300.0f; // Human tweaks in Inspector [Export] public PackedScene EnemyScene { get; set; } // Human assigns in Inspector // Group related exports [ExportGroup("Movement")] [Export] public float Speed { get; set; } = 100.0f; [Export] public float Acceleration { get; set; } = 10.0f; ``` ### Scene Instantiation ```csharp // Always check if assigned [Export] public PackedScene ProjectileScene { get; set; } private void Shoot() { if (ProjectileScene == null) { GD.PrintErr("ProjectileScene not assigned in Inspector"); return; } var bullet = ProjectileScene.Instantiate(); } ``` ## Standard C# Code Structure ```csharp using Godot; public partial class Player : CharacterBody2D { // Signals [Signal] public delegate void HealthChangedEventHandler(int newValue); // Constants private const float MaxSpeed = 400.0f; // Export variables [ExportGroup("Combat")] [Export] public int Damage { get; set; } = 10; [Export] public float AttackRate { get; set; } = 1.0f; // Private variables private string _currentState = "idle"; private Vector2 _velocity = Vector2.Zero; // Node references (initialized in _Ready) private Sprite2D _sprite; private Control _healthBar; // Godot callbacks public override void _Ready() { _sprite = GetNode("Sprite2D"); _healthBar = GetNode("%HealthBar"); // Unique name } public override void _PhysicsProcess(double delta) { // Physics logic } // Public methods public void TakeDamage(int amount) { // Implementation } // Private methods private void UpdateHealthBar() { // Implementation } // Signal callbacks private void _OnAreaEntered(Area2D area) { // Implementation } } ``` ## Resource Creation ```csharp // AI provides the Resource class definition using Godot; [GlobalClass] public partial class Recipe : Resource { [Export] public string Id { get; set; } = ""; [Export] public string[] Ingredients { get; set; } = Array.Empty(); [Export] public float InstabilityCost { get; set; } = 0.0f; } // Human creates instances: Right-click > Create Resource > Recipe ``` ## Testing & Debug Helpers ```csharp // Always include debug capability [Export] public bool DebugMode { get; set; } = false; // Debug methods public override void _Ready() { if (DebugMode) { GD.Print($"[{Name}] Ready with speed: {MoveSpeed}"); } } // Unit test methods (can be called from debugger or test scenes) public static float TestBrewingTiming() { float totalTime = 0.4f * 3 + 0.8f; // 3 ingredients + set time System.Diagnostics.Debug.Assert(totalTime < 2.5f, "Brewing too slow!"); return totalTime; } ``` ## Common C# Patterns ### Object Pooling Setup ```csharp // AI provides the structure, human assigns the scene [Export] public PackedScene PooledScene { get; set; } // Assign in Inspector private readonly Queue _pool = new(); private Node GetInstance() { if (_pool.Count == 0) return PooledScene.Instantiate(); return _pool.Dequeue(); } ``` ### State Machine ```csharp public enum State { Idle, Moving, Attacking } private State _currentState = State.Idle; private void TransitionTo(State newState) { _currentState = newState; switch (newState) { case State.Idle: _animationPlayer.Play("idle"); break; case State.Moving: _animationPlayer.Play("run"); break; } } ``` ## Instructions for Humans When AI generates code/scenes, it should include clear TODO comments: ```csharp // TODO: In Godot Editor: // 1. Assign EnemyScene in Inspector (drag Enemy.tscn) // 2. Set up collision shape (Circle, radius ~16) // 3. Add sprite texture // 4. Connect hurt_box's area_entered signal ``` ## What to Avoid ### DON'T - Hardcode paths to scenes (use [Export]) - Create complex AnimationPlayer tracks in code - Generate particle system parameters in code - Edit .import files - Assume node paths without proper initialization - Use old Godot 3 syntax or GDScript patterns in C# - Create collision polygons via code arrays - Modify project.godot directly - Create .gd files for game logic (use C# instead) - Create documentation files unless specifically requested - Use esotheric powershell one-liners for file manipulation (use the available tools or ask the user instead) ### DO - Use [Export] for all scene references - Use % for unique named nodes with GetNode - Include debug helpers - Check for null before using nodes - Use proper C# naming conventions (PascalCase for public, camelCase for private) - Provide fallbacks and error messages - Keep visual things in the editor - Use C# for all game logic and scripts ## File Organization Example ``` /project ├── /Scripts # All C# scripts organized by category │ ├── /Resources # Resource class definitions (AI creates these) │ │ └── Recipe.cs │ ├── /Player # Player-related scripts │ │ └── PlayerController.cs │ ├── /Enemies # Enemy-related scripts │ │ └── EnemyAI.cs │ ├── GameManager.cs # Global scripts at root level │ └── EventBus.cs ├── /Scenes # Mix of AI and human work, organized by category │ ├── /Player # Player-related scenes │ │ └── Player.tscn # AI creates structure, human adds visuals │ ├── /Enemies # Enemy-related scenes │ │ └── Enemy.tscn │ └── /UI # UI scenes │ └── MainMenu.tscn ├── /Resources # .tres resource files organized by category │ ├── /Recipes # Based on AI's Resource classes │ │ └── FireWaterSteam.tres │ └── /Items # Item resources │ └── Sword.tres ├── /Shaders # Shader files │ ├── Water.gdshader │ └── Fire.gdshader └── /Sprites # Human manages visual assets ├── /Player └── /Enemies ``` ## C# Specific Guidelines ### Naming Conventions - Classes: PascalCase (`PlayerController`) - Public properties/methods: PascalCase (`MoveSpeed`, `TakeDamage()`) - Private fields: _camelCase (`_currentHealth`, `_velocity`) - Constants: PascalCase (`MaxHealth`) - Enums: PascalCase (`PlayerState.Moving`) ### Property Usage ```csharp // Prefer properties over fields for exports [Export] public float Speed { get; set; } = 100.0f; // Use private fields for internal state private float _currentSpeed; ``` ### Null Safety ```csharp // Always check exported scenes/nodes if (ProjectileScene != null) { var projectile = ProjectileScene.Instantiate(); // Use the projectile } ``` ## Project-Specific Notes For **Your game**: ## Summary - AI handles: Logic, structure, systems in C# - Human handles: Visuals, feel, precise adjustments - .tscn files are human-readable and AI can generate them - Always use [Export] and Inspector for scene/resource references - Use C# for all game logic, GDScript only for EditorScript tools - Include debug modes and clear TODOs - Test core mechanics with static methods - Avoid creating documentation unless requested