Godot Integration Guide
๐ฎ Overview
This guide covers integrating the ItemDrops plugin into Godot 4.x games. The Godot integration provides Resource-based configuration, Node-based runtime components, and signal-based event handling.
๐ฆ Installation
Plugin Setup
- Copy the
ItemDropsfolder to your Godot project’saddons/directory - Enable the plugin in Project Settings โ Plugins
- Configure the ItemDrops settings as needed
Dependencies
- Godot 4.2+
- .NET 6.0+ (for C# support)
- No external dependencies required
๐๏ธ Architecture
Godot-Specific Components
ItemDrops.Godot/
โโโ Resources/
โ โโโ DropTable.cs # Resource for drop configuration
โ โโโ DropData.cs # Resource for individual drops
โ โโโ DropCondition.cs # Resource for drop conditions
โ โโโ ItemDropsBus.cs # Global drop management
โโโ Systems/
โ โโโ EnemyDrops.cs # Enemy drop component
โ โโโ ItemDropNode.cs # Dropped item node
โโโ Visuals/
โโโ DropEffects.cs # Visual effects for drops
Integration Pattern
- Resources: Configuration data stored as Godot Resources
- Nodes: Runtime behavior as Godot Nodes
- Signals: Event-driven communication
- Scene Tree: Integration with Godot’s scene system
๐ Quick Start
1. Create a Drop Table
// Create a new DropTable resource
var dropTable = new DropTable();
dropTable.MinDrops = 1;
dropTable.MaxDrops = 3;
dropTable.DropChance = 0.8f;
// Add some drops
var swordDrop = new DropData();
swordDrop.ItemId = "sword";
swordDrop.Weight = 2.0f;
swordDrop.Rarity = ItemRarity.Common;
dropTable.Drops.Add(swordDrop);
var potionDrop = new DropData();
potionDrop.ItemId = "health_potion";
potionDrop.Weight = 3.0f;
potionDrop.Rarity = ItemRarity.Common;
dropTable.Drops.Add(potionDrop);
// Save the resource
ResourceSaver.Save(dropTable, "res://data/drops/enemy_drops.tres");
2. Configure Enemy Drops
// Add EnemyDrops component to an enemy
public partial class Enemy : CharacterBody2D
{
[Export] public DropTable DropTable { get; set; }
public override void _Ready()
{
// Configure drop behavior
var enemyDrops = new EnemyDrops();
enemyDrops.DropTable = DropTable;
enemyDrops.AutoGenerateOnDeath = true;
AddChild(enemyDrops);
}
}
3. Handle Drop Events
public partial class Player : CharacterBody2D
{
public override void _Ready()
{
// Connect to drop events
ItemDropsBus.Instance.DropGenerated += OnDropGenerated;
}
private void OnDropGenerated(string itemId, Vector2 position)
{
GD.Print($"Drop generated: {itemId} at {position}");
}
}
๐ Resource Configuration
DropTable Resource
[Tool]
public partial class DropTable : Resource, IDropTable
{
[Export] public Godot.Collections.Array<DropData> Drops { get; set; }
[Export] public int MinDrops { get; set; } = 1;
[Export] public int MaxDrops { get; set; } = 1;
[Export] public float DropChance { get; set; } = 1.0f;
// Methods for drop generation
public Godot.Collections.Array<Node> GenerateDrops(Vector2 globalPosition)
public DropTableValidationResult Validate()
}
DropData Resource
[Tool]
public partial class DropData : Resource
{
[Export] public string ItemId { get; set; }
[Export] public float Weight { get; set; } = 1.0f;
[Export] public ItemRarity Rarity { get; set; } = ItemRarity.Common;
[Export] public int MinQuantity { get; set; } = 1;
[Export] public int MaxQuantity { get; set; } = 1;
[Export] public Godot.Collections.Array<DropCondition> Conditions { get; set; }
}
DropCondition Resource
[Tool]
public partial class DropCondition : Resource
{
[Export] public string ConditionType { get; set; }
[Export] public string StringValue { get; set; }
[Export] public int IntValue { get; set; }
[Export] public float FloatValue { get; set; }
}
๐ฏ Runtime Components
ItemDropsBus (Global Manager)
[Tool]
public partial class ItemDropsBus : Resource
{
// Singleton instance
public static ItemDropsBus Instance { get; }
// Default drop tables
[Export] public DropTable DefaultEnemyDrops { get; set; }
[Export] public DropTable DefaultBossDrops { get; set; }
// Global configuration
[Export] public float GlobalLuckModifier { get; set; } = 1.0f;
// Methods
public void RegisterDropTable(string id, DropTable dropTable)
public Godot.Collections.Array<Node> GenerateDrops(string tableId, Vector2 position)
public DropStatistics GetStatistics(string tableId, LootContext? context = null)
// Signals
[Signal] public delegate void DropGeneratedEventHandler(string itemId, Vector2 position);
[Signal] public delegate void DropCollectedEventHandler(string itemId, Node collector);
}
EnemyDrops Component
[Tool]
public partial class EnemyDrops : Node
{
[Export] public DropTable DropTable { get; set; }
[Export] public int LevelOverride { get; set; } = 0;
[Export] public string EntityTypeOverride { get; set; } = "";
[Export] public float LuckModifier { get; set; } = 1.0f;
[Export] public bool AutoGenerateOnDeath { get; set; } = true;
[Export] public float DropDelay { get; set; } = 0.5f;
[Export] public bool RandomOffset { get; set; } = true;
// Methods
public Godot.Collections.Array<Node> GenerateDrops()
public DropStatistics GetStatistics()
public void SetDropTable(DropTable dropTable)
}
ItemDropNode (Dropped Item)
[Tool]
public partial class ItemDropNode : Node2D
{
[Export] public string ItemId { get; set; }
[Export] public ItemRarity Rarity { get; set; }
[Export] public int Quantity { get; set; } = 1;
[Export] public bool AutoCollect { get; set; } = false;
[Export] public float CollectionRange { get; set; } = 50.0f;
// Methods
public void Configure(DropResult dropResult)
public void Collect(Node collector)
public void PlayCollectionEffects()
// Signals
[Signal] public delegate void CollectedEventHandler(string itemId, Node collector);
[Signal] public delegate void HoverStartEventHandler(string itemId);
[Signal] public delegate void HoverEndEventHandler(string itemId);
}
๐จ Visual Effects
Drop Effects
public partial class DropEffects : Node
{
// Particle effects for different rarities
[Export] public PackedScene CommonEffect { get; set; }
[Export] public PackedScene UncommonEffect { get; set; }
[Export] public PackedScene RareEffect { get; set; }
// Sound effects
[Export] public AudioStream DropSound { get; set; }
[Export] public AudioStream CollectSound { get; set; }
public void PlayDropEffect(Vector2 position, ItemRarity rarity)
public void PlayCollectEffect(Vector2 position, ItemRarity rarity)
}
Rarity-Based Visuals
public static class RarityVisuals
{
public static Color GetColor(ItemRarity rarity)
public static float GetGlowIntensity(ItemRarity rarity)
public static float GetParticleCount(ItemRarity rarity)
public static AudioStream GetSound(ItemRarity rarity)
}
๐ Advanced Usage
Conditional Drops
// Create level-based condition
var levelCondition = new DropCondition();
levelCondition.ConditionType = "MinimumLevel";
levelCondition.IntValue = 10;
// Create entity type condition
var entityCondition = new DropCondition();
entityCondition.ConditionType = "EntityType";
entityCondition.StringValue = "dragon";
// Add to drop data
dropData.Conditions.Add(levelCondition);
dropData.Conditions.Add(entityCondition);
Custom Drop Generation
public partial class CustomDropGenerator : Node
{
[Export] public DropTable DropTable { get; set; }
public override void _Ready()
{
// Generate drops with custom context
var context = new LootContext
{
Level = 25,
EntityType = "boss",
LuckModifier = 2.0f
};
var drops = DropTable.GenerateDrops(GlobalPosition, context);
foreach (var drop in drops)
{
AddChild(drop);
}
}
}
Loot Generation with Modifiers
// Create custom loot generator
var generator = ItemDropsBus.Instance.CreateLootGenerator(
"boss_loot",
new LuckModifier(1.5f),
new LevelBonusModifier(20, 2.0f),
new RarityFilterModifier(ItemRarity.Rare)
);
// Generate enhanced loot
var drops = ItemDropsBus.Instance.GenerateLoot(
"boss_loot",
"boss_table",
GlobalPosition
);
๐งช Testing in Godot
Unit Tests with GoDotTest
[Test]
public void TestDropGeneration()
{
// Create test drop table
var dropTable = new DropTable();
dropTable.AddDrop(new DropData { ItemId = "test_item", Weight = 1.0f });
// Generate drops
var drops = dropTable.GenerateDrops(Vector2.Zero);
// Assert results
Assert.That(drops.Count, Is.EqualTo(1));
Assert.That(drops[0].ItemId, Is.EqualTo("test_item"));
}
Integration Tests
[Test]
public void TestEnemyDropGeneration()
{
// Create test enemy
var enemy = new Enemy();
enemy.DropTable = LoadDropTable("test_enemy");
// Simulate death
enemy.EmitSignal("defeated");
// Verify drops generated
var drops = GetTree().GetNodesInGroup("drops");
Assert.That(drops.Count, Is.GreaterThan(0));
}
๐ง Performance Optimization
Object Pooling
public partial class DropNodePool : Node
{
private readonly Queue<ItemDropNode> _pool = new();
public ItemDropNode Get()
{
if (_pool.Count > 0)
{
return _pool.Dequeue();
}
return CreateNewDropNode();
}
public void Return(ItemDropNode node)
{
node.Reset();
_pool.Enqueue(node);
}
}
Batch Processing
public override void _Process(double delta)
{
// Process drops in batches for performance
var drops = GetTree().GetNodesInGroup("drops");
foreach (var batch in drops.Chunk(10))
{
ProcessDropBatch(batch);
}
}
๐ Common Issues & Solutions
Drop Generation Not Working
Problem: Drops not appearing when expected Solution:
- Verify drop table is properly configured
- Check that scene paths are correct
- Ensure AutoGenerateOnDeath is enabled
- Verify signal connections
Performance Issues
Problem: Lag when many drops are generated Solution:
- Use object pooling for drop nodes
- Limit simultaneous drops
- Optimize visual effects
- Use batch processing
Resource Loading Issues
Problem: Drop tables not loading correctly Solution:
- Check file paths and extensions
- Verify resources are saved properly
- Ensure proper export properties
- Check for circular references
๐ Best Practices
Resource Management
- Save drop tables as .tres files
- Use ResourceLoader for loading
- Implement proper validation
- Cache frequently used tables
Scene Integration
- Use proper node hierarchy
- Connect signals in _Ready()
- Clean up in _ExitTree()
- Use groups for organization
Performance
- Pool drop objects
- Limit visual effects
- Use spatial partitioning
- Optimize collision detection
Debugging
- Enable verbose logging
- Use Godot’s debugger
- Profile with Godot profiler
- Test with different drop rates
This guide evolves with the Godot integration development
Last Updated: November 2025
Godot Version: 4.2+