GodotNodeGenerator 0.0.1-alpha

This is a prerelease version of GodotNodeGenerator.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package GodotNodeGenerator --version 0.0.1-alpha
                    
NuGet\Install-Package GodotNodeGenerator -Version 0.0.1-alpha
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="GodotNodeGenerator" Version="0.0.1-alpha">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="GodotNodeGenerator" Version="0.0.1-alpha" />
                    
Directory.Packages.props
<PackageReference Include="GodotNodeGenerator">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add GodotNodeGenerator --version 0.0.1-alpha
                    
#r "nuget: GodotNodeGenerator, 0.0.1-alpha"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package GodotNodeGenerator@0.0.1-alpha
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=GodotNodeGenerator&version=0.0.1-alpha&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=GodotNodeGenerator&version=0.0.1-alpha&prerelease
                    
Install as a Cake Tool

Godot Node Generator

A C# source generator for Godot 4.x that creates strongly-typed accessors for nodes in your scenes.

Features

  • Automatically generates strongly-typed accessors for nodes in your Godot scenes
  • Enhanced type safety with proper error handling and null checks
  • TryGet methods for safe access without exceptions
  • Script and property detection for better code generation
  • Works with Godot 4.x C# projects
  • No runtime cost - all happens at compile time
  • Makes code more readable and maintainable
  • Prevents errors from typos in node paths or wrong type casts

Installation

  1. Install the NuGet package:
dotnet add package GodotNodeGenerator
  1. Add your scene files as AdditionalFiles in your project:
<ItemGroup>
    
    <AdditionalFiles Include="**/*.tscn" />
</ItemGroup>

Manual Installation

If you prefer to add the project directly:

  1. Add this project to your solution or include the compiled DLL as a reference
  2. Add the following to your .csproj file:
<ItemGroup>
    <ProjectReference Include="..\path\to\GodotNodeGenerator\GodotNodeGenerator.csproj"
                      OutputItemType="Analyzer"
                      ReferenceOutputAssembly="false" />
</ItemGroup>


<ItemGroup>
    
    <AdditionalFiles Include="**\*.tscn" />
    
    
    
    
</ItemGroup>

Usage

  1. Add your scene files as AdditionalFiles in your project file (.csproj)
  2. Apply the [NodeGenerator] attribute to your Godot node classes
  3. Specify the scene file path in the attribute constructor (or let it infer from class name)
  4. Use the generated properties to access nodes

Example

using Godot;
using GodotNodeGenerator;

namespace MyGame
{
    [NodeGenerator("res://scenes/Player.tscn")]
    public partial class Player : CharacterBody2D
    {
        public override void _Ready()
        {
            // Instead of GetNode<Sprite2D>("Sprite")
            Sprite.Texture = ResourceLoader.Load<Texture2D>("res://assets/player.png");
            
            // Instead of GetNode<Camera2D>("Camera")
            Camera.Current = true;
            
            // Instead of GetNode<AnimationPlayer>("AnimationPlayer")
            AnimationPlayer.Play("idle");
        }
    }
}

Generated code will look like:

// <auto-generated/>
using Godot;
using System;
using System.Diagnostics.CodeAnalysis;

namespace MyGame
{
    // Generated node accessors for Player
    public partial class Player
    {
        private Sprite2D? _Sprite;
        
        /// <summary>
        /// Gets the Sprite node (path: "Sprite")
        /// </summary>
        /// <exception cref="InvalidCastException">Thrown when the node is not of type Sprite2D.</exception>
        /// <exception cref="NullReferenceException">Thrown when the node is not found.</exception>
        [return: NotNull]
        public Sprite2D Sprite 
        {
            get
            {
                if (_Sprite == null)
                {
                    var node = GetNodeOrNull("Sprite");
                    if (node == null)
                    {
                        throw new NullReferenceException("Node not found: Sprite");
                    }
                    
                    _Sprite = node as Sprite2D;
                    if (_Sprite == null)
                    {
                        throw new InvalidCastException($"Node is of type {node.GetType()}, not Sprite2D");
                    }
                }
                
                return _Sprite;
            }
        }
        
        /// <summary>
        /// Tries to get the Sprite node without throwing exceptions.
        /// </summary>
        /// <returns>True if the node was found and is of the correct type.</returns>
        public bool TryGetSprite([NotNullWhen(true)] out Sprite2D? node)
        {
            node = null;
            if (_Sprite != null)
            {
                node = _Sprite;
                return true;
            }
            
            var tempNode = GetNodeOrNull("Sprite");
            if (tempNode is Sprite2D typedNode)
            {
                _Sprite = typedNode;
                node = typedNode;
                return true;
            }
            
            return false;
        }

        // Additional properties and TryGet methods for other nodes...
    }
}

Scene File Resolution

The generator looks for scene files that have been included as AdditionalFiles in your project. The AdditionalFiles mechanism is a standard Roslyn feature that allows source generators to access files without direct file I/O, which is important for incremental compilation and better IDE integration.

By default, it will look for a scene file with the same name as the class. For example, if your class is named Player, it will look for Player.tscn among your AdditionalFiles.

The source generator follows this process to find the scene file:

  1. Try to find a file that exactly matches the path specified in the attribute
  2. If not found, try to find a file with the same filename
  3. If the path doesn't have a .tscn extension, try adding it
  4. If still not found, use a dummy scene for testing purposes or report a diagnostic

You can override this by specifying the path in the attribute:

[NodeGenerator("res://scenes/custom_player.tscn")]
public partial class Player : CharacterBody2D
{
}

How It Works

The source generator:

  1. Identifies classes with the [NodeGenerator] attribute
  2. Parses the specified scene file to extract node information
  3. Generates strongly-typed accessors for each node
  4. Adds the generated code as a partial class

Type Safety Features

The generated code includes several type safety enhancements:

Safe Node Access

Each node property includes proper null checking and type validation:

public Camera2D Camera
{
    get
    {
        if (_Camera == null)
        {
            var node = GetNodeOrNull("Camera");
            if (node == null)
            {
                throw new NullReferenceException("Node not found: Camera");
            }
            
            _Camera = node as Camera2D;
            if (_Camera == null)
            {
                throw new InvalidCastException($"Node is of type {node.GetType()}, not Camera2D");
            }
        }
        
        return _Camera;
    }
}

Exception-free Access with TryGet Methods

For situations where you want to avoid exceptions, use the generated TryGet methods:

if (TryGetCamera(out var camera))
{
    // Camera exists and is of the correct type
    camera.Current = true;
}
else
{
    // Handle the case where the camera doesn't exist or is the wrong type
    GD.Print("Camera not available");
}

Script Detection

The generator detects scripts attached to nodes and includes this information in the property documentation:

/// <summary>
/// Gets the Player node (path: "Root/Player") (script: "res://scripts/Player.cs")
/// </summary>

This makes it easier to understand the relationship between scene nodes and script files.

Future Improvements

  • Support for nested node paths (e.g. "UI/HealthBar")
  • Support for binary (.scn) scene files
  • Automatic detection of scene files in the project
  • Enhanced error reporting and diagnostics

Testing

The project includes a comprehensive test suite targeting various components:

  • SceneParserTests: Tests the TSCN file parser with various scene structures
  • NodeGeneratorTests: Tests the source generator's code generation capabilities
  • SourceGenerationHelperTests: Tests the helper methods for code generation

To run tests, use the following command:

dotnet test

License

MIT License

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

  • .NETStandard 2.1

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.8-alpha 173 6/30/2025
0.0.7-alpha 150 6/30/2025
0.0.5-alpha 143 6/20/2025
0.0.4-alpha 149 6/20/2025
0.0.3-alpha 159 6/19/2025
0.0.2-alpha 157 6/19/2025
0.0.1-alpha 248 6/19/2025