Added godot copilot instructions

This commit is contained in:
MaddoScientisto 2026-02-08 14:59:10 +01:00
commit b5a1c8c759

View file

@ -0,0 +1,395 @@
# 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>("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>("Sprite2D");
_healthBar = GetNode<Control>("%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<string>();
[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<Node> _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<Projectile>();
// 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