7.7 KiB
7.7 KiB
Godot C# Library Management with Git Submodules
Overview
Manage reusable C# libraries across multiple Godot projects using Git submodules. Each library is a separate repository that game projects include as submodules.
Directory Structure
~/GameDev/
├── Godot/ # Engine installation
├── libraries/ # Local library development
│ ├── utilities/
│ ├── audio-manager/
│ └── ui-framework/
└── projects/ # Game projects
├── test-game/
│ └── Libraries/ # Git submodules
│ ├── utilities/
│ └── audio-manager/
└── puzzle-game/
└── Libraries/
└── utilities/
Git Organization:
library/org - Reusable librariesproject/org - Game projects
Prerequisites
- Godot v4.5.1+ (C# support)
- .NET 8.0+
- Git with Gitea access
- Gitea organizations:
libraryandproject
Create a Library
1. Initialize Repository
cd ~/GameDev/libraries
git init utilities
cd utilities
mkdir -p Scripts
2. Configure Library
project.godot:
[application]
config/name="Utilities Library"
config/features=PackedStringArray("4.3", "C#", "Forward Plus")
[dotnet]
project/assembly_name="EinSoftworks.Utilities"
Utilities.csproj:
<Project Sdk="Godot.NET.Sdk/4.3.0">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<RootNamespace>EinSoftworks.Utilities</RootNamespace>
<AssemblyName>EinSoftworks.Utilities</AssemblyName>
</PropertyGroup>
</Project>
3. Add Code
Scripts/MathUtils.cs:
using Godot;
namespace EinSoftworks.Utilities
{
public static class MathUtils
{
public static float Clamp01(float value) => Mathf.Clamp(value, 0f, 1f);
public static bool Approximately(float a, float b, float threshold = 0.001f)
=> Mathf.Abs(a - b) < threshold;
public static float DegreesToRadians(float degrees) => degrees * Mathf.Pi / 180f;
public static float RadiansToDegrees(float radians) => radians * 180f / Mathf.Pi;
}
}
4. Create .gitignore
.godot/
.import/
.mono/
bin/
obj/
*.tmp
export_presets.cfg
5. Commit and Push
git add .
git commit -m "Initial utilities library"
git remote add origin https://git.ein-softworks.com/library/utilities.git
git branch -M main
git push -u origin main
Create a Game Project
1. Initialize Project
cd ~/GameDev/projects
git init test-game
cd test-game
mkdir -p Scripts Scenes Libraries
2. Configure Project
project.godot:
[application]
config/name="Test Game"
config/features=PackedStringArray("4.3", "C#", "Forward Plus")
run/main_scene="res://Scenes/Main.tscn"
[dotnet]
project/assembly_name="TestGame"
TestGame.csproj:
<Project Sdk="Godot.NET.Sdk/4.3.0">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<RootNamespace>TestGame</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="Libraries/utilities/Utilities.csproj" />
</ItemGroup>
</Project>
3. Add Library as Submodule
git submodule add https://git.ein-softworks.com/library/utilities.git Libraries/utilities
git submodule update --init --recursive
4. Use Library in Code
Scripts/Main.cs:
using Godot;
using EinSoftworks.Utilities;
namespace TestGame
{
public partial class Main : Node2D
{
public override void _Ready()
{
float radians = MathUtils.DegreesToRadians(90f);
GD.Print($"90° = {radians} rad");
}
}
}
5. Create Scene and Commit
Create Scenes/Main.tscn in Godot, then:
cp ../utilities/.gitignore .
git add .
git commit -m "Initial test game with utilities library"
git remote add origin https://git.ein-softworks.com/project/test-game.git
git branch -M main
git push -u origin main
Common Operations
Update Library to Latest
cd ~/GameDev/projects/test-game
git submodule update --remote Libraries/utilities
git add .
git commit -m "Update utilities library"
git push
In Godot: Project → Reload Current Project, then rebuild.
Update to Specific Version
cd ~/GameDev/projects/test-game/Libraries/utilities
git checkout v1.2.0
cd ../..
git add Libraries/utilities
git commit -m "Update utilities to v1.2.0"
git push
Add Another Library
cd ~/GameDev/projects/test-game
git submodule add https://git.ein-softworks.com/library/audio-manager.git Libraries/audio-manager
Update TestGame.csproj:
<ItemGroup>
<ProjectReference Include="Libraries/utilities/Utilities.csproj" />
<ProjectReference Include="Libraries/audio-manager/AudioManager.csproj" />
</ItemGroup>
git add .
git commit -m "Add audio-manager library"
git push
Create New Project with Existing Libraries
cd ~/GameDev/projects
git init puzzle-game
cd puzzle-game
mkdir -p Scripts Scenes Libraries
# Add libraries
git submodule add https://git.ein-softworks.com/library/utilities.git Libraries/utilities
git submodule add https://git.ein-softworks.com/library/audio-manager.git Libraries/audio-manager
git submodule update --init --recursive
# Create project.godot and .csproj with references
# (see example structure above)
git add .
git commit -m "Initial puzzle game setup"
git remote add origin https://git.ein-softworks.com/project/puzzle-game.git
git push -u origin main
Clone Project on New Machine
git clone --recursive https://git.ein-softworks.com/project/test-game.git
# Or if already cloned
cd test-game
git submodule update --init --recursive
Library Dependencies
If one library depends on another, reference it in the .csproj:
Libraries/ui-framework/UIFramework.csproj:
<ItemGroup>
<ProjectReference Include="../utilities/Utilities.csproj" />
</ItemGroup>
Version Control
Create Library Release
cd ~/GameDev/libraries/utilities
git tag -a v1.0.0 -m "Release v1.0.0 - Initial stable release"
git push origin v1.0.0
Development Workflow
# Library development
cd ~/GameDev/libraries/utilities
git checkout -b feature/new-utils
# Make changes
git add .
git commit -m "Add new utility functions"
git push origin feature/new-utils
# Merge in Gitea, then pull main
git checkout main
git pull origin main
# Update in project
cd ~/GameDev/projects/test-game
git submodule update --remote Libraries/utilities
git add .
git commit -m "Update utilities to latest"
git push
Best Practices
Library Design:
- Keep libraries focused and single-purpose
- Use namespace pattern:
CompanyName.LibraryName - Document public APIs with XML comments
- Use semantic versioning (major.minor.patch)
Project Organization:
- Use kebab-case for repos, PascalCase for namespaces
- Only include needed libraries
- Test after library updates
Git Workflow:
- Use feature branches for development
- Write clear commit messages
- Push changes regularly
- Tag important releases
Troubleshooting
Submodule empty:
git submodule update --init --recursive
Build errors:
- Godot → Project → Reload Current Project
- Project → Tools → C# → Create C# solution
- Rebuild
Missing references:
Check .csproj has all <ProjectReference> entries.
Submodule update conflicts:
cd Libraries/utilities
git stash
git pull origin main
git stash pop
IntelliSense not working:
- Reload Godot project
- Rebuild solution
- Restart VS Code with project folder open