{"id":42685467,"url":"https://github.com/outfox/2dog","last_synced_at":"2026-04-11T19:14:30.666Z","repository":{"id":331623550,"uuid":"1131628177","full_name":"outfox/2dog","owner":"outfox","description":"🦴 2dog is Godot in .NET","archived":false,"fork":false,"pushed_at":"2026-04-11T12:28:07.000Z","size":1382,"stargazers_count":106,"open_issues_count":7,"forks_count":6,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-11T14:20:36.983Z","etag":null,"topics":["csharp","dotnet","gamedev","godot","godot-engine","godot4","godotengine","libgodot"],"latest_commit_sha":null,"homepage":"https://2dog.dev/","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/outfox.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-10T11:45:20.000Z","updated_at":"2026-04-11T12:28:09.000Z","dependencies_parsed_at":"2026-03-16T15:03:58.991Z","dependency_job_id":null,"html_url":"https://github.com/outfox/2dog","commit_stats":null,"previous_names":["outfox/2dog"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/outfox/2dog","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outfox%2F2dog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outfox%2F2dog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outfox%2F2dog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outfox%2F2dog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/outfox","download_url":"https://codeload.github.com/outfox/2dog/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outfox%2F2dog/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31684577,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-11T13:07:20.380Z","status":"ssl_error","status_checked_at":"2026-04-11T13:06:47.903Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","dotnet","gamedev","godot","godot-engine","godot4","godotengine","libgodot"],"created_at":"2026-01-29T12:16:47.170Z","updated_at":"2026-04-11T19:14:30.656Z","avatar_url":"https://github.com/outfox.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# How *do you* pronounce `Godot` ? 🦴\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/content/public/logo-animated.svg\" alt=\"2dog logotype, a white stylized dog with the negative space around its leg forming the number 2, and a playful font spelling the word dog\" width=\"70%\"\u003e\n\u003c/p\u003e\n\n[![Discord Invite](https://img.shields.io/badge/discord-_%E2%A4%9Coutfox%E2%A4%8F-blue?logo=discord\u0026logoColor=f5f5f5)](https://discord.gg/GAXdbZCNGT)\n[![NuGet](https://img.shields.io/nuget/v/2dog?color=blue)](https://www.nuget.org/packages/2dog/)\n[![Build Status](https://github.com/outfox/2dog/actions/workflows/build-natives.yml/badge.svg)](https://github.com/outfox/2dog/actions/workflows/build-natives.yml)\n[![CI](https://github.com/outfox/2dog/actions/workflows/ci.yml/badge.svg)](https://github.com/outfox/2dog/actions/workflows/ci.yml)\n\n\u003e *\"Godot, or to dog... is it even a question?\"*\n\nThis library lets your C# application code start and pump Godot's MainLoop - not the other way around.\n\n---\n\n## What is 2dog?\n\n**2dog** is a .NET/C# front-end for [Godot Engine](https://github.com/godotengine/godot) that inverts the traditional architecture. Instead of having Godot's process and scene tree drive your application, **you** now control Godot as a library.\n\nThink of it like this: Godot is your loyal companion that follows your lead, learns new tricks, and does exactly what you tell it to. All this while still having all the capabilities of the full engine.\n\n```cs\nusing twodog;\n\nusing var engine = new Engine(\"myapp\", \"./project\");\nusing var godot = engine.Start();\n\n// Load a scene\nvar scene = GD.Load\u003cPackedScene\u003e(\"res://game.tscn\");\nengine.Tree.Root.AddChild(scene.Instantiate());\n\n// Run the main loop\nwhile (!godot.Iteration())\n{\n    // Your code here – every frame\n}\n```\n\n### What does this mean?\n\n- 🎮 **Full Godot Power** – access the complete GodotSharp API: scenes, physics, rendering, audio, input – everything Godot can do\n- 🔄 **Inverted Control** – your .NET process controls Godot, not the other way around\n- 🧪 **First-Class Testing** – built-in xUnit fixtures for testing Godot code, run headless in CI/CD pipelines\n\n---\n\n## Features\n\n- Godot as an embedded library (libgodot)\n- Full GodotSharp API access\n- Custom .NET-first project structure\n- Three build configurations: Debug, Release, and Editor (with `TOOLS_ENABLED`)\n- xUnit test fixtures (`GodotFixture`, `GodotHeadlessFixture`)\n- `dotnet new` project templates\n- Headless mode for servers and CI/CD\n\n\u003e **Prerelease packages are now available on NuGet!** Supported platforms: `win-x64`, `linux-x64`, `osx-arm64`.\n\n---\n\n## Quick Start\n\n### Prerequisites\n- .NET SDK 8.0 or later\n- [Godot (.NET)](https://godotengine.org/) (for importing project assets)\n\n### Using Templates (Recommended)\n\n```bash\n# Install the template (bundled in the main 2dog package)\ndotnet new install 2dog\n\n# Create a new project (optionally with xUnit tests)\ndotnet new 2dog --tests True -n MyGame\n\n# Navigate into the project\ncd MyGame\n\n# Import assets or just open with Godot Editor of your choide\ngodot-mono --path MyGame.Godot --import\n\n# Run tests\ndotnet test\n\n# Run the game\ndotnet run --project MyGame\n\n# Edit in Godot at any time\ngodot-mono -e --path MyGame.Godot\n```\n\n### Adding to an Existing Project\n\n```bash\ndotnet add package 2dog\n```\n\n---\n\n## Known Issues\n\n### Single Godot Instance Per Process\n\nOnly one Godot instance can exist per process. Attempting to start a second instance will throw an `InvalidOperationException`. This is a fundamental constraint of the Godot engine.\n\n### xUnit Test Discovery Crash with Godot Types\n\nUsing Godot types (like `NodePath`, `StringName`, `Vector2`, etc.) in xUnit `[MemberData]` will crash the test runner during discovery. This happens because xUnit enumerates test data before tests run, instantiating Godot types before the engine is initialized.\n\n**Crashes during discovery:**\n```csharp\npublic static IEnumerable\u003cobject[]\u003e paths = [[new NodePath(\"/root\")]];\n\n[Theory]\n[MemberData(nameof(paths))]\npublic void MyTest(NodePath path) { }\n```\n\n**Workaround:** Add `DisableDiscoveryEnumeration = true`:\n```csharp\n[MemberData(nameof(paths), DisableDiscoveryEnumeration = true)]\n```\n\nOr use primitive types and construct Godot objects inside the test:\n```csharp\npublic static IEnumerable\u003cobject[]\u003e paths = [[\"/root\"]];\n\n[Theory]\n[MemberData(nameof(paths))]\npublic void MyTest(string pathStr)\n{\n    var path = new NodePath(pathStr);\n    // ...\n}\n```\n\n---\n\n### Building from Source\n\nIf you prefer to build everything locally instead of using NuGet packages:\n\n1. **Clone and initialize submodules**\n```bash\ngit clone --recursive https://github.com/outfox/2dog\ncd 2dog\n```\n\n2. **Build Godot** (requires Python with uv)\n```bash\nuv run poe build-godot\n```\n\n3. **Build .NET packages**\n```bash\nuv run poe build\n```\n\n\u003e You can also run `uv run poe build-all` to do steps 2 and 3 in one go.\n\n4. **Run the demo**\n```bash\ndotnet run --project demo\n```\n\n### Build Configurations\n\n```bash\ndotnet build -c Debug    # Development with debug symbols\ndotnet build -c Release  # Optimized production build\ndotnet build -c Editor   # Editor tools with TOOLS_ENABLED\n```\n\n\u003e Tested on `win-x64`, `linux-x64`, and `osx-arm64`.\n\n---\n\n## Documentation\n\nFull documentation at **[2dog.dev](https://2dog.dev)**\n\n- [Getting Started](https://2dog.dev/getting-started.html) – installation and first project\n- [Core Concepts](https://2dog.dev/concepts.html) – architecture and design\n- [Build Configurations](https://2dog.dev/build-configurations.html) – Debug, Release, and Editor modes\n- [API Reference](https://2dog.dev/api-reference.html) – Engine, GodotInstance, and more\n- [Testing with xUnit](https://2dog.dev/testing.html) – test fixtures and CI/CD setup\n- [Project Templates](https://2dog.dev/templates.html) – scaffolding new projects\n\n---\n\n## Join the Pack\n\nQuestions? Ideas? Want to teach 2dog new tricks?\n\n---\n\n## Acknowledgements\n\nInspired by and built upon Ben Rog-Wilhelm's [libgodot_example](https://github.com/zorbathut/libgodot_example/tree/csharp).\n*You're the GOAT. Or a [DIESEL HORSE](https://diesel.horse). Same difference!*\n\n---\n\n#### *No squirrels were harmed in the making of this README.*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foutfox%2F2dog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foutfox%2F2dog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foutfox%2F2dog/lists"}