362 lines
7.7 KiB
Markdown
362 lines
7.7 KiB
Markdown
# 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 libraries
|
|
- `project/` org - Game projects
|
|
|
|
## Prerequisites
|
|
|
|
- Godot v4.5.1+ (C# support)
|
|
- .NET 8.0+
|
|
- Git with Gitea access
|
|
- Gitea organizations: `library` and `project`
|
|
|
|
## Create a Library
|
|
|
|
### 1. Initialize Repository
|
|
|
|
```bash
|
|
cd ~/GameDev/libraries
|
|
git init utilities
|
|
cd utilities
|
|
mkdir -p Scripts
|
|
```
|
|
|
|
### 2. Configure Library
|
|
|
|
**project.godot:**
|
|
```ini
|
|
[application]
|
|
config/name="Utilities Library"
|
|
config/features=PackedStringArray("4.3", "C#", "Forward Plus")
|
|
|
|
[dotnet]
|
|
project/assembly_name="EinSoftworks.Utilities"
|
|
```
|
|
|
|
**Utilities.csproj:**
|
|
```xml
|
|
<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:**
|
|
```csharp
|
|
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
|
|
|
|
```gitignore
|
|
.godot/
|
|
.import/
|
|
.mono/
|
|
bin/
|
|
obj/
|
|
*.tmp
|
|
export_presets.cfg
|
|
```
|
|
|
|
### 5. Commit and Push
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
cd ~/GameDev/projects
|
|
git init test-game
|
|
cd test-game
|
|
mkdir -p Scripts Scenes Libraries
|
|
```
|
|
|
|
### 2. Configure Project
|
|
|
|
**project.godot:**
|
|
```ini
|
|
[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:**
|
|
```xml
|
|
<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
|
|
|
|
```bash
|
|
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:**
|
|
```csharp
|
|
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:
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
cd ~/GameDev/projects/test-game
|
|
git submodule add https://git.ein-softworks.com/library/audio-manager.git Libraries/audio-manager
|
|
```
|
|
|
|
Update **TestGame.csproj**:
|
|
```xml
|
|
<ItemGroup>
|
|
<ProjectReference Include="Libraries/utilities/Utilities.csproj" />
|
|
<ProjectReference Include="Libraries/audio-manager/AudioManager.csproj" />
|
|
</ItemGroup>
|
|
```
|
|
|
|
```bash
|
|
git add .
|
|
git commit -m "Add audio-manager library"
|
|
git push
|
|
```
|
|
|
|
### Create New Project with Existing Libraries
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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:**
|
|
```xml
|
|
<ItemGroup>
|
|
<ProjectReference Include="../utilities/Utilities.csproj" />
|
|
</ItemGroup>
|
|
```
|
|
|
|
## Version Control
|
|
|
|
### Create Library Release
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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:**
|
|
```bash
|
|
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:**
|
|
```bash
|
|
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
|