I have been using Neovim as my main code editor for a while now. So I try to configure it to work with any coding project that I have to do. Configuring Neovim to work with something can take a while on it’s own, but I think it’s worth it in the long run since you get to learn more about to tools you use.
Anyways, this time I will write about how I managed to get C# language server, Omnisharp, to work with Neovim in Unity development. I have this configuration working on Linux, macOS, and Windows (Git Bash). At the time of writing, the versions of each components are as follows:
Neovim: v0.9.1
Unity Hub: v3.5.0
Unity Editor: 2022.3.5f1
Omnisharp: v1.39.8
Operating Systems:
- Arch Linux
- macOS Ventura
- Windows 10 22H2
Omnisharp
Omnisharp is a language server, when configured properly, it will send diagnostics and auto completion (IntelliSense) data to the editor. Omnisharp can be enabled in Visual Studio Code by installing the official C# extension, and needs a little bit of configuration for it to work with Unity (settings useModernNet
to false
). Since omnisharp is quite flexible, we can adapt it to work with other editors as well.
Mono
Mono is the framework that enables .NET development on platforms like Linux and macOS, we’ll need it to run Omnisharp on Linux and macOS. For Windows, native omnisharp can be used.
Prerequisites
Before diving into the configuration, let’s make sure the required software are installed. The main component needed to run Omnisharp is .NET SDK. You will also need mono and mono version of msbuild if you’re on Linux or macOS.
On Linux and macOS, to check if you have the required components installed, make sure these commands can be executed:
dotnet --version
msbuild --version
mono --version
Installation Instructions
If you’re using one of the distros/Operating Systems below, the following instructions can be used to install .NET SDK, mono, and mono version of msbuild.
Ubuntu
Since the mono version of msbuild isn’t in the default repository in Ubuntu, you will need to add the mono repository yourself. Follow the instructions at: https://www.mono-project.com/download/stable/
After you added the repository, the following command can be used to install the needed components:
apt install dotnet-sdk-7.0 mono-devel msbuild
Arch Linux
Luckily for Arch and Arch-based distribution, the needed components should be in the default repository. To install, run the following command:
pacman -S dotnet-sdk mono mono-msbuild
macOS
In macOS, dotnet and mono can be downloaded from the official sites.
https://dotnet.microsoft.com/download/
Windows
For Windows, make sure dotnet
is executable in your editor. This can be done by installing .NET SDK then set up the Path environment variable.
The configuration
Assuming you have a working Neovim configuration with nvim-lspconfig
and mason
as the package manager, you can install omnisharp-mono
from mason if you’re on macOS / Linux, and omnisharp
if you’re on Windows (Git Bash)
Mono Omnisharp
Since nvim-lspconfig
doesn’t support configuring omnisharp-mono
installed from mason by default, we have to add it as a custom server. To do this, the following code can be used to add the custom server, note that this must be run before server configuration:
if not configs.omnisharp_mono then
configs.omnisharp_mono = {
default_config = {
cmd = { 'omnisharp-mono', '--languageserver', '--hostPID', tostring(vim.fn.getpid()) },
filetypes = { 'cs' },
root_dir = lspconfig.util.root_pattern('*.csproj', '*.sln', '.git'),
settings = {}
}
}
end
After the server is added, the following code can be used to set useModernNet
to false, which is required for Unity development. In the code below, monoPath = vim.fn.system {'which', 'mono'}
is also added to help set correct path for mono
executable which also helps make the same config work on both macOS and Linux.
require'lspconfig'.omnisharp_mono.setup{
settings = {
useModernNet = false,
monoPath = vim.fn.system { 'which', 'mono' }
}
}
Native omnisharp (Windows)
Since native Omnisharp doesn’t require mono to function and omnisharp
can be configured in nvim-lspconfig
, the following config can be used to set useModernNet
to false.
require'lspconfig'.omnisharp.setup{
settings = {
useModernNet = false
}
}
Opening C# file in Neovim
For Omnisharp to start, the following conditions has to be met:
- Neovim is opening a
.cs
file .csproj
exists in the project root
In case there are no .csproj
files in project root, it can be regenerated in Unity in Preferences > External Tools > Regenerate project files.
If configured properly, Omnisharp should run. However, give Omnisharp some time to start. From my experience, Omnisharp usually starts up after around 1-2 minutes. Please note that :LspInfo
will show Omnisharp as other clients that match the filetype: cs
until it is successfully attached.
Troubleshooting
omnisharp-mono not executable
It occured to me once that the run
script from omnisharp-mono
package has wrong permissions. To fix that, make the run
script in /home/naborisk/.local/share/nvim/mason/packages/omnisharp-mono
executable by running:
chmod +x ~/.local/share/nvim/mason/packages/omnisharp-mono/run
MonoBehavior not getting recognized
Make sure mono
is executable in your PATH
Lastly
My full configuration can be found in my dotfiles repository. It took some effort to get Omnisharp working properly with Unity development, but being able to use the editor you’re used to in development is awesome! Though Omnisharp takes a moment to start up, Neovim starts up pretty fast