【vscode/Unity】monoを認識せず、インテリセンスが消えたときの対処法

# この記事の注意

~~対処法とありますが、根本的な解決にはなっておらず単なる回避策です。~~

>一応解決しました。

過程はどうでもいい！って方は記事の一番最後だけで問題ないです。

# 環境

  OS: macOS 12.0.1 (21A559)
  vscode: 1.63.1
  dotnet: 5.0.404
  mono: 6.12.0.162
  
  Unity: 2020.3.24f1
  Visual Studio Code Editor: Version 1.2.4 - September 01, 2021
  
# 原因を突き止めるまでの一連の流れ
## 現象

vscodeでunityのスクリプトを書いていると**頻繁に**インテリセンスが消えます。
インテリセンスがなければUnityEngineなんてとても扱えません。

monoだの.NETだのomnisharpだの色々エラーを吐きます。
調べると同様の現象が多発しているようで、さまざまな対処法が書かれていますが結局明確な解決策は見つかりませんでした。
（例えば再起動とか再インストールなんかすると治ったりしますが結局いずれ再発します。）
今日こそはこの原因を突き止めようと奮起して特攻したわけです。
  
## エラーメッセージをよく確認

インテリセンスの核であるomnisharpがエラーを吐いていました。

```
Starting OmniSharp server at 12/16/2021, 1:52:22 PM
    Target: /Users/username/Unity/Projects/projectname/projectname.sln

[ERROR] Error: Unable to find Mono. Ensure that Mono's '/bin' folder is
added to your environment's PATH variable.
```

omnisharpがmonoを見つけられないようです。
binファイルへのpathを追加しろとのことですが...

## pathの中身を確認

```
❯ echo $PATH
/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/share/dotnet:~/.dotnet/tools:/Library/Apple/usr/bin:
/Library/Frameworks/Mono.framework/Versions/Current/Commands
```

後ろの方にある

```
/Library/Apple/usr/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands
```

が~~monoのpathのはずですが~~念の為binファイルの在処を探ります。

>どうやらこれは**monoのコマンド用**のpathっぽいです。

## 発見

```
❯ which mono
/Library/Frameworks/Mono.framework/Versions/Current/Commands/mono

~/Unity/Projects/projectname
❯ ls -la /Library/Frameworks/Mono.framework/Versions/Current/
total 24
drwxr-xr-x   14 root  admin   448 Dec 15 12:06 .
drwxr-xr-x    4 root  admin   128 Dec 15 12:06 ..
drwxr-xr-x  123 root  admin  3936 Dec 15 12:06 Commands
-rw-r--r--    1 root  admin    11 Dec  1 00:52 VERSION
drwxr-xr-x  293 root  admin  9376 Dec 15 12:06 bin
drwxr-xr-x    6 root  admin   192 Dec 15 12:06 etc
-rw-r--r--    1 root  admin     0 Dec 15 12:06 gtk-query-immodules-2.0.log
drwxr-xr-x   41 root  admin  1312 Dec 15 12:06 include
drwxr-xr-x  217 root  admin  6944 Dec 15 12:06 lib
-rw-r--r--    1 root  admin     0 Dec 15 12:06 postinstall-fc-cache.log
-rw-r--r--    1 root  admin   319 Dec 15 12:06 postinstall-gdk-pixbuf-query-loaders.log
-rw-r--r--    1 root  admin     0 Dec 15 12:06 postinstall-pango-querymodules.log
drwxr-xr-x   16 root  admin   512 Dec  1 00:52 share
-rw-r--r--    1 root  admin    47 Dec  1 00:52 updateinfo
```

5行目にbinファイルがあるのでpathを追加します。これで解決？

```
❯ export PATH=/Library/Frameworks/Mono.framework/Versions/Current/:$PATH 
```

## が、ダメ

omnisharpを再起動してもpathが通りません。謎です。

## vscodeの設定を確認

>Omnisharp: Use Global Mono
Launch OmniSharp with the globally-installed Mono. If set to "always", "mono" version 6.4.0 or greater must be available on the PATH. If set to "auto", OmniSharp will be launched with "mono" if version 6.4.0 or greater is available on the PATH.

なにやらGlobal Monoを使いたいならver6.4.0以上のmonoのpathを有効にしろと言っています。
そこでmonoのバージョンを確認

```
Mono JIT compiler version 6.12.0.162
```

...😠

## 内蔵のmonoを使う

調べたところ、omnisharp自体にmonoが内蔵されており、通常はそのmonoを使う模様。そこで

```
"omnisharp.useGlobalMono": "never"
```

と設定して内蔵monoを使おうとすると...

```
OmniSharp.MSBuild.ProjectManager
        Attempted to update project that is not loaded
```

やら

```
This project targets .NET version that requires reference assemblies that 
do not ship with OmniSharp out of the box (e.g. .NET Framework). The most 
common solution is to make sure Mono is installed on your machine 
(https://mono-project.com/download/) and that OmniSharp is started with 
that Mono installation (e.g. "omnisharp.useGlobalMono":"always" in C# 
Extension for VS Code).
```

やらエラーを吐きまくります。
とにかくmonoをインストールせよって感じです。もうしてる。

## 詰み

たらい回しにされて詰んでしまいました。😇

# 回避策（原理不明）

上記で探したpath等を追加する必要はありません。
最新のmonoをインストールし、

```
"omnisharp.useGlobalMono": "always"
```

の状態で次の手順を踏めばpathが通ります。

1. まずUnityを開きます。
2. 適当なスクリプトからvscodeを開きます
3. この時点ではmonoを認識しませんが、ここでcmd+Qでvscodeを終了します
4. 再度適当な方法でスクリプトを開きます。
5. pathが通りインテリセンスが復活します。

3.のタイミングでcmd+shift+Wで閉じる場合はpathは通らないままです。（要するに、×ボタンでvscodeのウインドウを閉じても意味がない。）
vscodeのコマンドでomnisharpやwindowをリスタートしてもpathは通りません。探した限りcmd+Qでしかpathが通りません。

**とにかくインテリセンスが働かないならcmd+Qで復活します。**

私は「エラー吐いてインテリセンスが効かなかったけどいつの間にか治ってた」という現象に何度か遭遇しているんですが、「いつの間にか治ってた」というのは「いつの間にかvscodeを終了してた」ということだと思います。

# 解決策発見（謎は残っているが...）

```
"omnisharp.useGlobalMono": "always",
"omnisharp.monoPath":"/Library/Frameworks/Mono.framework/Versions/Current"
```

settings.jsonにこのように/Currentのpathを指定することでインテリセンスが復活します。
**このpathは何故かterminalからでは通らないのでsetting.jsonに書き込む必要があります。**
ただし

```
[fail]: OmniSharp.MSBuild.ProjectLoadListener
Unexpected exception got thrown from project load listener:
System.NullReferenceException:
Object reference not set to an instance of an object
```
というような謎のNullReferenceExceptionが大量に出るのでこれで何も問題がないかは不明です。
しかしとにかくインテリセンスは使えます。


# そもそもなぜpathが通らないのか

わかりません。
そもそも回避策で通過できる理由もかなり謎です。