📌

Unityでasmdefを適用しつつC#10の機能を使う

に公開

Unityで最新のC#機能を使う方法(C# 10/11以降)

Unityの公式C#サポートは現在C# 9.0までですが、C# 10や11には便利な機能があります。
Unity 2022.2以降には新しいC#コンパイラがすでに入っていて、設定を変えるだけでこれらの新機能を使えるようになります。


Unityとコードエディタの両方の設定

新しいC#バージョンをUnityで使うには、2つの場所で設定を変える必要があります。

  1. Unityエディタのコンパイラ: Unityがゲームをビルドしたり動かしたりするときにコードをチェックする部分です。
  2. コードエディタ(Visual Studio Codeなど): コードを書くときに使うソフトです。コードの入力補助やエラー表示をしてくれます。

この2つの設定が合っていないと、Unityでは動くのにVSCodeではエラーが出るといったことが起きます。


ステップ1: UnityのコンパイラをC# 10にする (csc.rsp)

まずは、UnityにC# 10を使うように指示します。これにはcsc.rspというファイルを使います。

.asmdefファイルを使っている場合

もし.asmdef(アセンブリ定義ファイル)を使ってコードを分けているなら、それぞれの.asmdefがあるフォルダに設定が必要です。
C# 10の機能を使いたいアセンブリのフォルダ(.asmdefファイルがある場所)に、csc.rspという名前のファイルを作り、次の1行を書き込みます。

-langVersion:10

例えば、Assets/Scripts/MyGame/CoreというフォルダにCore.asmdefがあるなら、Assets/Scripts/MyGame/Core/csc.rspを作ります。これを、C# 10を使いたいアセンブリの数だけ繰り返します。


ステップ2: コードエディタもC# 10にする (CsprojModifier)

次に、VSCodeのようなコードエディタがコードを正しく理解できるように設定します。この作業を自動でやってくれる便利なツールCsprojModifierを使います。

1. CsprojModifierを入れる

UnityのPackage Managerを開き、以下のURLからパッケージをインストールします。

https://github.com/Cysharp/CsprojModifier.git?path=src/CsprojModifier/Assets/CsprojModifier

2. LangVersion.propsファイルを作る

Unityプロジェクトのルートフォルダに、LangVersion.propsという名前のファイルを作り、以下の内容を書き込みます。

<Nullable>enable</Nullable>も一緒に入れておくと、C# 8.0以降で使えるNull許容参照型が有効になります。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <LangVersion>10.0</LangVersion>
        <Nullable>enable</Nullable>
    </PropertyGroup>
</Project>

3. CsprojModifierを設定する

Unityエディタで Project Settings > Editor > C# Project Modifier を開きます。

  1. Additional project imports:
    • 「+」ボタンを押して、パスに LangVersion.props と入力します。
  2. The project to be added for Import.:
    • .asmdefを使っている場合、C# 10を使いたいすべてのアセンブリの.csprojファイル名をここに追加します。例えば、Core.asmdefがあるなら Core.csproj をリストに入れます。

設定が終わったら、ウィンドウの下にあるRegenerate project filesボタンを押して、変更を反映させます。


ステップ3: C# 9.0の互換性対策 (IsExternalInit)

C# 9.0で追加されたinitセッター(一度だけ値を設定できる機能)やrecord型(データ構造を簡単に作れる機能)を使うには、System.Runtime.CompilerServices.IsExternalInitという特別な型が必要です。Unityが使っている古い.NETバージョンにはこれが含まれていないため、自分で用意する必要があります。

なぜ複数のファイルが必要なのか?

このIsExternalInitクラスをinternalで定義した場合、その定義は同じアセンブリの中でしか有効になりません。そのため、C# 9.0以降の機能を使いたいすべてのアセンブリに、このクラスのファイルを置く必要があります。

次の内容でIsExternalInit.csというファイルを作り、必要なアセンブリのフォルダにそれぞれ置きます。

namespace System.Runtime.CompilerServices
{
    /// <summary>
    /// C# 9.0 の init; や record 型を、古い .NET バージョンで利用するために必要な型。
    /// このクラスをプロジェクトに追加することで、CS0518 エラーを回避できます。
    /// </summary>
    internal static class IsExternalInit
    {
    }
}

問題と解決策

FileNotFoundException / DirectoryNotFoundException が出る

CsprojModifierがLangVersion.propsを見つけられないというエラーです。

  • 原因: CsprojModifierの設定で指定したパスと、ファイルの実際の場所が違っています。
  • 解決策: LangVersion.propsファイルがプロジェクトの一番上のフォルダに正しく置かれているか確認し、CsprojModifierの設定ではパスを「LangVersion.props」とだけ入力してください。

CS8773: Feature '...' is not available in C# 9.0. が出る

このエラーは、どこで出ているかによって原因が異なります。

  • VSCodeなどのコードエディタだけで出る場合: CsprojModifierの設定ミスです。C# 10を使いたい.csprojファイルが設定リストに追加されているか、LangVersion.propsが正しく読み込まれているか確認してください。
  • Unityエディタのコンソールで出る場合: csc.rspファイルの設定漏れです。エラーが出ているアセンブリの.asmdefファイルと同じフォルダに、-langVersion:10と書かれたcsc.rspファイルが置かれているか確認してください。

まとめ

Unityで最新のC#機能を使うには、次の3つの設定が必要です。

  1. csc.rsp: Unityが使うC#のバージョンをC# 10にする。
  2. CsprojModifier + LangVersion.props: コードエディタが使うC#のバージョンをC# 10にする。
  3. IsExternalInit.cs: C# 9.0のinitrecord型を古い.NET環境で使えるようにする。

これらの設定を行うことで、Unityでも最新のC#機能を使った効率的な開発が可能になります。

参考

https://zenn.dev/chorome/articles/ce2d86608e55fc

Discussion