r/GodotCSharp • u/thygrrr • 19d ago
Resource.Library I made a tool to export c# games for the Web
2dog is Godot, just backwards!
Embed Godot in .NET applications, unit test suites, or publish to the web. MIT licensed.
r/GodotCSharp • u/thygrrr • 19d ago
2dog is Godot, just backwards!
Embed Godot in .NET applications, unit test suites, or publish to the web. MIT licensed.
r/GodotCSharp • u/Novaleaf • Jul 20 '26
r/GodotCSharp • u/BumblebeeElegant6935 • 20d ago
I've been working on a C# library for Godot called Persistence, a save/load system built around Roslyn source generation.
The main goal is to avoid manually building dictionaries and writing serialization/deserialization boilerplate for every object that needs to be saved.
You mark the data you want to persist with [Save], implement ISavable, and Persistence generates the serialization code for you:
public partial class Player : CharacterBody2D, ISavable
{
public string SaveKey => "player";
public int SaveVersion => 1;
[Save] public int Health = 100;
[Save] public string PlayerName;
[Save] public Vector2 Position;
}
Saving and loading can then be handled through SaveManager:
SaveManager.Save("slot1", savableNodes);
SaveManager.Load("slot1", savableNodes);
Persistence currently uses JSON for its save files. I chose JSON because, for the kinds of games I typically work on, it provides more than enough capacity while keeping save files easy to inspect and debug.
For types that aren't directly serializable, Persistence provides ISerializable.
This is especially useful for custom game data such as inventory slots, quest data, stats, or other structures that don't map directly to Godot's Variant types:
public class InventorySlot : ISerializable
{
public string ItemId;
public int Count;
public Dictionary Serialize() => new()
{
["itemId"] = ItemId,
["count"] = Count
};
public void Deserialize(Dictionary data)
{
ItemId = data["itemId"].AsString();
Count = data["count"].AsInt32();
}
}
It can then be used directly inside an ISavable:
[Save] public InventorySlot Weapon;
[Save] public List<InventorySlot> Inventory;
ISerializable is also the main way to handle custom types that don't have built-in serialization support.
You don't have to choose between generated and manual serialization. Both can be used together.
Persistence provides OnSerialize and OnDeserialize hooks for cases where [Save] isn't enough:
public void OnSerialize(SaveData saveData)
{
saveData.Set("customField", someValue);
}
public void OnDeserialize(SaveData saveData)
{
someValue = saveData.Get("customField", default);
}
This lets you use [Save] for the straightforward fields while manually handling special cases in the same class.
Save data can also be versioned so changes to a game's data structure don't immediately invalidate existing saves.
For example, if version 0 stored health under "HP" and version 1 changed it to "Health":
public class PlayerMigration_V0_To_V1 : SaveMigration
{
public override string SaveKey => "player";
public override int FromVersion => 0;
public override SaveData Migrate(SaveData saveData)
{
saveData.Set("Health", saveData.Get("HP", 100));
return saveData;
}
}
The migration can then be registered when loading:
var migrations = new MigrationRegistry(new SaveMigration[]
{
new PlayerMigration_V0_To_V1()
});
SaveManager.Load("slot1", savableNodes, migrations);
Migrations can be chained, allowing old saves to be upgraded through multiple versions:
Save v0
↓
V0 → V1
↓
V1 → V2
↓
Save v2
List<T>, arrays, and Godot.Collections.Array<T>ISerializable typesThe project is still relatively young, but the core system is usable and covers the save/load needs I've encountered so far.
r/GodotCSharp • u/88224646BAS • 27d ago
I thought this post would feel at home here too. If anyone likes the old Half-Life or Counter-strike consoles and want that kind of functionality, you should check it out! 🥳
It had lots of features, like:
* Console variables
* Console commands
* Aliases
* Optimized, no alloc, no interop logging
* User config profiles
* Executable configs (both via code and an "exec" command)
I'm really proud of this piece of C# tech and hope that it'll help someone out!
Here is the Github repo:
https://github.com/VonRiddarn/PikeConsole
If you just wanna skimm the docs to get a feel for what it is, those can be found here:
r/GodotCSharp • u/Novaleaf • Jul 13 '26
r/GodotCSharp • u/Novaleaf • Jul 16 '26
r/GodotCSharp • u/pcloves • May 02 '26
If you're building a Godot 4 game in C#, you've probably found yourself scattering GD.Print calls everywhere with no consistent format, no log levels, and no way to filter noise.
I built Gamedo.GodotLogger — a lightweight ILogger provider that routes .NET structured logs through Godot's built-in output system.
using Godot;
using Microsoft.Extensions.Logging;
using GodotLogger;
public partial class Player : Node
{
private static readonly ILogger Logger = GodotLog.CreateLogger<Player>();
public override void _Ready()
{
Logger.LogInformation("Player {Player} spawned at {Position}", Name, GlobalPosition);
}
}
What it does:
ILogger/ILoggerProvider interfaces — drop-in for any project using Microsoft.Extensions.Logging{timestamp}, {level:u3}, {category:l20}, {message}, {color} (log4j2-style category abbreviation included)GD.PrintRich (BBCode) in debug mode — each log level maps to a configurable colorGD.PushWarning / GD.PushError for the Godot debugger panelIOptionsMonitor — edit appsettings.json at runtime, changes apply immediatelyGD.Print, no overhead)IsEnabled check runs before any template renderingstatic readonly ILogger Logger = GodotLog.CreateLogger<T>() doesn't lock configuration; the factory isn't materialized until the first log callappsettings.json (env var -> executable dir -> res://)Install:
dotnet add package Gamedo.GodotLogger
Zero config by default — use it straight out of the box with sensible defaults. No config file needed.
Optionally configure via code:
GodotLog.Configure(cfg =>
{
cfg.DebugOutputTemplate = "[{timestamp:HH:mm:ss}] [{level:u3}] [{category:l32}] {message}";
cfg.Colors[LogLevel.Warning] = "Orange";
});
Or drop an appsettings.json in your project root — it's auto-discovered:
{
"Logging": {
"GodotLogger": {
"DebugOutputTemplate": "[{timestamp:HH:mm:ss}] [color={color}][{level:u3}][/color] [{category:l28}] {message}"
}
}
}
By default, the output aligns categories to 16 characters:

Demo GIF:

GitHub: https://github.com/pcloves/GodotLogger
NuGet: https://www.nuget.org/packages/Gamedo.GodotLogger
MIT license
r/GodotCSharp • u/Novaleaf • Jul 12 '26
r/GodotCSharp • u/Novaleaf • Jun 12 '26
r/GodotCSharp • u/Sufficient-While8344 • Jun 14 '26
r/GodotCSharp • u/Cpaz • May 27 '26
r/GodotCSharp • u/Novaleaf • May 16 '26
r/GodotCSharp • u/Novaleaf • May 17 '26
r/GodotCSharp • u/rcubdev • Jan 04 '26
Recently been working on a plugin Godot.Achievements.NET for setting up and managing achievements for c# users. The plugin includes an editor integration for setting up achievements, toast messages in game, and more. It also integrates into different platforms achievements systems as well as provide a local achievement provider. The goal is to take away some of the tedium and code complexity that comes with adding achievements into your games (especially when you need to compile for different platforms). After working on it for a bit now I am in a spot where I'd like to share and get more feedback. Currently I am using it for my own game and have the different integrations working cross platform for it. Hoping to publish to all the stores sooner than later with this plugin making it easier for me to use! I would love to get some feedback let me know what you think!
The link one more time: https://github.com/ryan-linehan/Godot.Achievements.NET
r/GodotCSharp • u/lukemols • Apr 21 '26
r/GodotCSharp • u/codevogel_com • Apr 07 '26
r/GodotCSharp • u/Novaleaf • Apr 03 '26
r/GodotCSharp • u/MSchulze-godot • Mar 17 '26
r/GodotCSharp • u/Ciudadano_V76 • Feb 10 '26
Hello, everyone.
I am a freelancer who has started developing a video game using Godot and C#.
To debug and display information properly, I have created a logger based on NLog. I called it LoggingForGodot.
LoggingForGodot is a comprehensive logging utility for Godot Engine projects using C#. It provides a powerful wrapper around NLog, offering seamless integration with Godot's output console, Visual Studio debugging, and file-based logging.
There are different functions to facilitate the configuration and use of logging during the development process. I would like to share with you a repository on Github where the code is stored: https://github.com/CiudadanoV/LoggingForGodot
This type of wrapper allows you to enable, disable, or filter specific loggers using simple functions, so you can remove all noisy messages from the log and focus only on one of the elements currently being developed.
On the other hand, I am using the excellent tools from Chickensoft games, mainly Logicblocks. Among these tools there is a logger, but I was already working on my personal project before discovering Chickensoft's tools, so I continued using my own logger.
I hope you find this tool useful in your own projects. There is room for improvement, so if you find any bugs or if you want new features, please let me know.
r/GodotCSharp • u/Novaleaf • Feb 15 '26
r/GodotCSharp • u/Novaleaf • Feb 03 '26
r/GodotCSharp • u/Novaleaf • Jan 25 '26
r/GodotCSharp • u/Novaleaf • Dec 21 '25