Godot, Nvim, C#, and GDscript

⧞ Table of Contents

I've been playing around with Godot 4.4/4.5 for a while now, but using the integrated editor is quite frustrating compared to a real code editor or IDE. There are some vim plugins out there, but I wanted a more lightweight solution. So I looked into configuring Neovim and it ended up being simpler than I expected.

Nvim

I build my nvim using nix with nvf. I added treesitter and grammars via nix:

{
    config.vim.treesitter = {
        enable = true;
        grammars = with pkgs.vimPlugins.nvim-treesitter.builtGrammars; [
            gdscript
            gdshader
            godot-resource
        ];
    };
}

For the gdscript treesitter grammar, I used lua:

local lspconfig = require('lspconfig')
local util = require('lspconfig.util')

local function is_godot_project()
    local cwd = vim.fn.getcwd()
    return vim.fn.filereadable(cwd .. '/project.godot') == 1
end

if is_godot_project() then
    lspconfig.gdscript.setup({
        cmd = {'nc', 'localhost', '6005'},
        root_dir = util.root_pattern('project.godot', '.git'),
        filetypes = {'gd', 'gdscript'},
    })
end

This took care of gdscript. For C#, I went with omnisharp. Godot-mono generates a .csproj and .sln in the project directory, so all I had to do was build the project once and then I was able to open files in nvim.

All that was left was dotnet and mono, which I manage via a flake for the project, as I prefer to not install these globally:

{
  description = "godot";

  outputs = {
    self,
    nixpkgs,
    flake-utils,
    ...
  } @ inputs:
    flake-utils.lib.eachDefaultSystem (system: let
      pkgs = import nixpkgs {inherit system;};

      dotnetPkg = pkgs.dotnetCorePackages.combinePackages [
        pkgs.dotnet-sdk_9
        pkgs.dotnet-sdk_8
      ];
      requiredPaths = [
        dotnetPkg
        pkgs.csharprepl
        pkgs.tracy-glfw
      ];
    in {
      devShells.default = pkgs.mkShell rec {
        nativeBuildInputs = [pkgs.autoPatchelfHook];
        buildInputs = requiredPaths;
        DOTNET_CLI_TELEMETRY_OPTOUT = 1;
        DOTNET_ROOT = "${dotnetPkg}/share/dotnet";
        TRACY_PATH = "${pkgs.lib.getExe pkgs.tracy-glfw}";
      };
    });

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
    flake-utils.url = "github:numtide/flake-utils";
  };
}

Godot

Of course, if you want C# support, you need to use godot-mono instead of regular godot. Nix provides both variants:

{pkgs, ...}: {
    home.packages = with pkgs; [
        godotPackages_4_5.godot
        godotPackages_4_5.godot-mono
    ];
}

In my game project, I went to Editor > Network > Language Server and made sure Remote Host was set to 127.0.0.1, and Remote Port was set to 6005. Advanced settings needs to be enabled.

Under Editor > Text Editor > Behavior, I set Auto reload scripts on external change and Auto reload and parse scripts on save to On.

You can go to Editor > Text Editor > External to configure what happens if you click a script file in the godot engine UI. My preference is to not enable it in settings, and just files using nvim in a separate window anyway.

Posts from blogs I follow