Unityで最新の"C#"(C#13 previewも)を使う方法

2024/07/06に公開

はじめに

https://github.com/DaZombieKiller/UnityRoslynUpdater
上記のレポジトリを見かけて
2024/7/6日現在でもC#12が使えるとわかったので、
具体的方法とpreview段階であるC#13まで使う場合の注意などを書いていきたいと思います。

ちょっと危険だけどファイル スコープ名前空間とMonoBehaviourの問題も解消できます。

↓Forkして言語バージョン指定をできるようにしたものです。
https://github.com/Akeit0/UnityRoslynUpdater

Windows限定でC#12を使う

何が起こっているかや応用を知っていた方がいいですが、
Windows限定では簡単な方法があるので、結論から言います。
なければ.NET8をインストールする。(C#13がしたいなら.NET9) 
下記のレポジトリのどちらかをダウンロードする。
https://github.com/DaZombieKiller/UnityRoslynUpdater
https://github.com/Akeit0/UnityRoslynUpdater
UnityRoslynUpdaterのフォルダのcmdで

dotnet publish -c Release -r win-x64 --no-self-contained -p:DebugType=none -p:PublishSingleFile=true

と打つ。(これはBuildなので1度でよい)
そこから\artifacts\bin\UnityRoslynUpdater\release_win-x64
に移動して6000.0.5f1なら

UnityRoslynUpdater.exe "C:\Program Files\Unity\Hub\Editor\6000.0.5f1\Editor"

と打つ。(previewなどバージョン指定するならこちら限定で最後に"Preview"などつけることで設定できます。)

これで、C#12が使え、Unity2022以降ではfile-scoped namespaceでもMonoBehaviourが認識されるようになります。

既に知られているC#10,11を使う方法

すでにC#10,11を使う方法はある程度知られています。
CsprojModifierを用いた方法でこちらでに手順をまとめられた記事があります。

この方法でなぜうまくいくかと言うとUnityが使うC#コンパイラがC#11に対応したものになっているものの、ランタイムと不整合を起こすことからデフォルトでC#9に抑えられています。
それをcsprojで置き換えることでC#11まで使うというものです。

C#12~を使う方法

前節にあったようにUnityが使うC#コンパイラがC#11ということなので、そこを置き換えればC#12でもC#13(.NET9 preview)も使えます。
コピーしてきてもいいですが、比較的安全なシンボリックリンクを使います。
シンボリックリンクとはファイルやフォルダがリンクになっていて、一見そこにリンク先のファイルやフォルダがあるかのように(Unityからも)見せられるものです。(Windows/Mac 両者にあります。)

Unityの使うコンパイラのフォルダと対応する.NETのフォルダは

Windowsでは
Unity 6000.0.5f1側
C:\Program Files\Unity\Hub\Editor\6000.0.5f1\Editor\Data\NetCoreRuntime
C:\Program Files\Unity\Hub\Editor\6000.0.5f1\Editor\Data\DotNetSdkRoslyn
.NET 8.0.302側
C:\Program Files\dotnet
C:\Program Files\dotnet\sdk\8.0.302\Roslyn\bincore

ここをシンボリックリンクで結びつけます。
ここから手順になります。(Windows)
バージョンは適切に読み替えてください。

  1. もし.NETがなければ.NET8をインストールする。
    (もしC#13がしたいなら.NET9)
  2. Unityのフォルダはバックアップとして退避させる。
    C:\Program Files\Unity\Hub\Editor\6000.0.5f1\Editor\Data\NetCoreRuntime
    C:\Program Files\Unity\Hub\Editor\6000.0.5f1\Editor\Data\DotNetSdkRoslyn
    (コマンドプロンプトなら管理者権限で開き
cd "C:\Program Files\Unity\Hub\Editor\6000.0.5f1\Editor\Data"
mkdir BuiltInSdk
move NetCoreRuntime BuiltInSdk
move DotNetSdkRoslyn BuiltInSdk
  1. (既に開いていなければ)管理者権限でコマンドプロンプトを開き、コマンドを打つ。
mklink /d "C:\Program Files\Unity\Hub\Editor\6000.0.5f1\Editor\Data\NetCoreRuntime" "C:\Program Files\dotnet"
mklink /d "C:\Program Files\Unity\Hub\Editor\6000.0.5f1\Editor\Data\DotNetSdkRoslyn" "C:\Program Files\dotnet\sdk\8.0.302\Roslyn\bincore"

以上で置き換えは完了です。
CsprojModifierでlangversionをlatestもしくはpreviewにすると対応する.NETのlatest、previewになります。

ここから既存のDllを書き換える話

UnityRoslynUpdaterではCsprojModifierなしでもlangversionがC#12になります。
これはUnityEditor.Compilation.ScriptCompilerOptionsにあるset_LanguageVersion関数(おそらくプロパティ)でC#9に設定されるところを書き換えることで、実現されています。

またUnity 2022からMonoBehaviourが認識する機能はUnity.SourceGenerators.dllによるものになっています。
それにともなってかfile名と一致させなくてもよいなど仕様変更がありました。
https://docs.unity3d.com/6000.0/Documentation/Manual/Namespaces.html
file-scoped namespaceでもMonoBehaviourが認識されるようにするところも同様にこのdllの書き換えによるものです。

DLL書き換えはより問題になりうるので、ここはしないというのがBetterかも。

ランタイムの制限

ここまでC#を最新にする方法を書いてきましたが、UnityのC#のRuntime(CLR)が更新されたわけではないのでIDEではかけても、コンパイルエラーになるなどの制限があります。
READMEにまとめられています。

コンパイルエラーにならない分かりづらいものもあります。
C#12ではコレクション式が追加され

int[] array = [3,5,6];

のように書けますが、
InlineArrayを用いて

Span<int> span = [3,5,6];

をGC.Allocなしに実現しています。
InlineArrayがRuntimeでサポートされてない環境(つまりUnity)では、

Span<int> span = new Span<int>(new int[3]{ 3, 5, 6 });

のようにコンパイルされ、見えないGC.Allocになってしまいます。

C#13の話

.NET9 previewはVisualStudio2022 previewのみ対応しています。
IDEで作業されると思いますがC#13を使うならVisualStudio2022 previewを使いましょう。

まとめ

CoreCLRが来ていない現状のUnityでも最新のC#が使えることがわかりました。
間違えなどがあったら訂正のコメント、
改めてMacの情報のコメントなどをお待ちしております。

Discussion