Note
This project is not affiliated with Unity Technologies.
Debugging is also supported:
Ready-to-use Neovim configuration with the Unity engine. This repository is a single README file that provides instructions on how to setup Neovim for Unity game engine development tasks. This project aims to provide both, a ready-to-use Neovim package and a guide on how to get Neovim working with Unity all while relying on permissive licenses for thirdy party tools/plugins providers (i.e., no Microsoft licenses that forces telemetry)
If you already have your own Neovim configuration and want to know how to get it working with Unity, you can easily follow this README as a guide on how to do that.
It is assumed that readers of this guide have a basic knowledge of IDE concepts,
Neovim, and Lua (and to very little extent C#). In case the reader is new to
concepts like LSP (language server protocol) and DAP (debug adapter protocol),
there are collapsed sections under the name New to X?
describing the concepts
very briefly but clearly enough to get started with incorporating them into your
Neovim configuration.
This Installation guide targets Linux distributions. A guide on how to properly set this for Windows(and MacOS) is yet to be provided.
Neovim installation commands on:
Ubuntu
sudo add-apt-repository ppa:neovim-ppa/unstable -y
sudo apt update
sudo apt install make gcc ripgrep unzip git xclip neovim
Debian
sudo apt update
sudo apt install make gcc ripgrep unzip git xclip curl
# Now we install nvim
curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim-linux-x86_64.tar.gz
sudo rm -rf /opt/nvim-linux-x86_64
sudo mkdir -p /opt/nvim-linux-x86_64
sudo chmod a+rX /opt/nvim-linux-x86_64
sudo tar -C /opt -xzf nvim-linux-x86_64.tar.gz
# make it available in /usr/local/bin, distro installs to /usr/bin
sudo ln -sf /opt/nvim-linux-x86_64/bin/nvim /usr/local/bin/
Fedora Install Steps
sudo dnf install -y gcc make git ripgrep fd-find unzip neovim
Arch
sudo pacman -S --noconfirm --needed gcc make git ripgrep fd unzip neovim
Windows
-
install chocolatey either follow the instructions on the page or use winget, run in cmd as admin:
winget install --accept-source-agreements chocolatey.chocolatey
-
install all requirements using choco, exit the previous cmd and open a new one so that choco path is set, and run in cmd as admin:
choco install -y neovim git ripgrep wget fd unzip gzip mingw make
This project has been tested with Unity6000.1 LTS. Any tests on other Unity versions are extremely appreciated!
First of all make sure that you have installed Neovim >= 0.11. You can do that by following this guide.
-
If you already have a Neovim configuration, you can ignore the following steps and jump to Installing Dependencies. It is best however to take a look into how the C# LSP and Unity debugging are configured in CGNvim to avoid annoying pitfalls.
If you want to use the configuration proposed by this project, make sure to do a backup of your own configuration (assuming you have one):
mv ~/.config/nvim ~/.config/nvim.bak mv ~/.local/share/nvim ~/.local/share/nvim.bak
-
Then clone the CGNvim repository (Neovim configuration for general purpose computer graphics development):
git clone https://github.com/walcht/CGNvim.git ~/.config/nvim
For C# Language Server Protocol (LSP) support, you have to:
-
globally install .NET SDK >= 9.0. It can be installed from the following official source: .NET SDK installation guide
-
download the Roslyn Language Server as a NuGet package from:
- on Linux: Roslyn LS Linux
- on Windows: Roslyn LS Windows
- on MacOS: Roslyn LS MacOS
-
extract it (NugGets are ZIP archives) at some location of your choice (that we hereafter refer to as <roslyn_ls_path>):
-
open the Roslyn LSP configuration file (or your custom Neovim's Roslyn LS configuration file) using some text editor:
nvim ~/.config/nvim/lua/cgnvim/lsps/roslyn_ls.lua
and change the cmd
path to where you extracted/installed the Roslyn LSP:
cmd = {
'dotnet',
'<roslyn_ls_path>/Microsoft.CodeAnalysis.LanguageServer.dll',
'--logLevel', -- this property is required by the server
'Information',
'--extensionLogDirectory', -- this property is required by the server
fs.joinpath(uv.os_tmpdir(), 'roslyn_ls/logs'),
'--stdio', -- adjust accordingly in case you want to communicate with the
-- LSP via TCP
},
where <roslyn_ls_path>
has to be the folder you extracted the Roslyn LSP NuGet
package to.
Note: you might have heard of Omnisharp as another C# LSP, avoid using it as it is being(?) discontinued and has major memory leakage issues.
Roslyn LSP (and all(?) other C# LSPs) works by analyzing the generated solution (.sln) and .csproj files from the provided C# project(s)/solution(s). These project files have to be initially generated then updated whenever a C# script is updated or a new C# script is created.
Essentially, some Unity plugin has to automatically handle this. The same plugin should also be able to instantiate a Neovim instance (in case one is not already instantiated) and communicate with it (e.g., when clicking on a Unity Console Log error, the plugin has to open the corresponding file at the appropriate location).
This is exactly how Visual Studio (also VSCode and Rider) is integrated for Unity development tasks. The plugin in this case is installed by default (check Package Manager for the officially supported Visual Studio Editor plugin).
In the case of Neovim, the custom plugin com.walcht.ide.neovim has to be installed for proper Neovim support. In the Unity Editor, in the top menu bar navigate to:
Window -> Package Management -> Package Manager -> navigate to plus sign on top left -> Install package from git URL...
then enter:
https://github.com/walcht/com.walcht.ide.neovim.git
and click on install.
Now when navigating to: Edit -> Preferences -> External Tools
you should
see Neovim
in the drop down options.
To automatically open Neovim when clicking on files/console warnings or errors, navigate to:
Edit -> Preferences -> External Tools
then Set "External Script Editor" to
Neovim.
Adjust which packages to generate the .csproj files for (you will only get LSP functionalities for those selected packages and you might - not verified - get worse performance the more the selected):
Now try to open a C# script from you project and keep an eye on the notifications that might pop-up.
Some plugins require external tools to be installed.
For a start, make sure the latest versions of these are installed:
- Git
- (optional) NPM
- (optional) Python >= 3.9
Type :checkhealth
in a Neovim instance to check for missing dependencies.
Plugins with missing dependencies should be clearly identified and a simple
internet search with the dependency's name will yield the official installation
guide.
For LSP to work properly .csproj files have to be generated from the project
files. If you enter the command :LspInfo
after opening a .cs file from a
Unity project, you might notice that the project's directory root wasn't
detected (see image below). The project directory has to be detected for
Omnisharp to work properly (Think of across-files go-to definitions and
references or classes defined in external modules like UnityEngine, UnityEditor
etc.).
Getting a C# LSP (in this case Roslyn LS) to work properly for a Unity project can be frustrating.
To debug LSP issues, make sure that the C# LSP is active by entering the command
:LspInfo
and checking the output. Do also check the LSP logs using the command
:LspLog
(important to note that a lot of LSP errors and warnings can be
safely ignored).
Make sure to run :checkhealth
to check if installed plugins are working
properly. If any issues are encountered then it is, most probably, related to
some plugin dependencies that are not (or not properly) installed.
The Mono debug adapter for Unity VSCode Unity Debug is no longer supported and is deprecated, therefore a fork of the project is created at Unity-DAP to provide an up-to-date debug adapter for Unity (without any VSCode dependencies).
To add debugging support for Unity, you have to:
-
install Mono
-
install the Unity debug adapter by cloning the repo and building it from source:
git clone --recurse-submodules https://github.com/walcht/unity-dap.git cd unity-dap dotnet build unity-debug-adapter/unity-debug-adapter.csproj --configuration=Release
-
Assuming you are using the CGNvim Neovim configuration, navigate to
~/.config/nvim/lua/cgnvim/daps/unity.lua
and change theunity-debug-adapter.exe
path (also optionally changemono
path in case it is not in PATH):-- adjust mono path - do not use Unity's integrated MonoBleedingEdge command = "mono", -- adjust unity-debug-adapter.exe path args = { "<path-to-unity-debug-adapter.exe>", "--log-level=none", -- optional log level argument: tace | debug | info | warn | error | critical | none -- "--log-file=<path-to-log-file>", -- optional path to log file (logs to stderr in case this is not provided) },
-
If you are debugging a Unity editor instance, make sure Unity is set to
Mode: Debug
and if you are debugging a Unity player instance, then make sure that it is debuggable (check the settings on how to do that). -
Open a C# script, set some breakpoints and continue ( key or by
:DapContinue
) -
The Unity DAP connects to the Unity Mono debugger via a TCP socket, therefore you have to provide an IP address and a port. On Linux, you can figure the debugging port of a Unity editor instance by checking the output of:
ss -tlp | grep 'Unity'
which yields an output like this:
LISTEN 0 16 127.0.0.1:56365 0.0.0.0:* users:(("UnityShaderComp",pid=306581,fd=128),("Unity",pid=306365,fd=128)) LISTEN 0 16 127.0.0.1:56451 0.0.0.0:* users:(("UnityShaderComp",pid=322591,fd=47),("Unity",pid=322451,fd=47)) LISTEN 0 16 127.0.0.1:56457 0.0.0.0:* users:(("UnityShaderComp",pid=322609,fd=47),("Unity",pid=322457,fd=47))
the debugging IP is 127.0.0.1 and the port is 56365. (ideally the list of endpoints to connect to should be listed automatically - will be implemented in the near future)
In case you are not using the CGNvim Neovim configuration, just copy its DAP configuration for Unity and adapt it to your configuration.
Note
Unity-DAP only supports debugging applications built using the scripting backend Mono
(i.e., IL2CPP debugging is not supported). Read the caution below in case debugging
IL2CPP-built applications is a necessity for you.
Alternatively, if you want to bebug IL2CPP-built apps then the new official extension
for VSCode, albeit closed-source, provides a UnityDebugAdapter.dll
and a UnityAttachProbe.dll
which *can be used to list multiple instances with which the DAP client could be attached.
Caution
You will be in breach of the license terms for the extension if you use it for Neovim development. To quote the license terms:
(a) Use with In-Scope Products and Services. You may install and use the Software only with Microsoft Visual Studio Code, vscode.dev, GitHub Codespaces (“Codespaces”) from GitHub, Inc. (“GitHub”), and successor Microsoft, GitHub, and other Microsoft affiliates’ products and services (collectively, the “In-Scope Products and Services”).
For this reason, I started a project to provide an up-to-date debug adapter under an MIT license.
- Windows support (CRUCIAL)
- Provide a set of default keymaps as a PDF 'cheat sheet' (IMPORTANT)
- MacOS support (IMPORTANT)
- Add XML comments highlighting (OPTIONAL)
- Add GitHub pages support (OPTIONAL)
- Q. Why not use omnisharp or csharp-ls?
- A. Roslyn LS is the new officially suporrted LSP for C#. Omnisharp is not well maintained, can be exteremely slow and unresponsive, and has a potential memory leak issue. CSharp-LS on the other hand is a hacky LSP (as per the description in its repository) and is not officially supported.
- Q. Why the headache? Why not just use Visual Studio/VSCode?
- A. Some people find great joy in using Neovim. Some other people use it for all their programming tasks thus it would be inefficient for them to transition to Visual Studio or VSCode just for Unity programming. Also, Neovim consumes less resources and you get more control into how much you want it to act as an IDE.
- Q. Why when opening a .cs script, nvim opens multiple empty buffers?
- A. Make sure that the name of your Unity project does not contain any white spaces.
- Q. Syntax highlighting doesn't seem to work. What should I do?
- A. Check whether Treesitter (syntax highlighting plugin) is working properly.
- Q. Why does LSP take so long (e.g., couple of seconds) to provide completion at the start of Neovim?
- A. The language server has to read your whole project (or part of it - depending on the LSP settings) for proper LSP setup. A little bit of patience at the start is needed. As instructed in the beginning of this guide, just avoid using Omnisharp - it has numerous issues including severe memory leakage problems.
- Q. LSP stopped working/does not work, help!
- A. Check LSP log by entering
:LspInfo
and solve issues accordingly.
The objective for this guide and its related projects is to provide a rich Neovim development experience for the Unity game engine. Any feedback is more than welcome (especially regarding C# LSP details).
MIT License. See LICENSE.txt file for more info.