Open1

Unity で使えるライブラリのソリューションとプロジェクト(とテスト)を dotnet CLI で生成する

Agate PrisAgate Pris

マネージプラグイン を使えば、より新しいバージョンの .NET Standard プロファイル、 .NET Framework プロファイル、そして .NET Framework API を用いたダイナミックリンクライブラリを使うことができるが、ここでは「Unity のビルドシステムと、通常の Visual Studio プロジェクト・ソリューションの双方でビルド可能なプロジェクト」を目指す。

そうすることで(たぶん)以下のメリットが得られる。

  • バイナリを配布しなくていいので楽。
  • Unity が自動生成するプロジェクトで、編集不要でブレークポイントを利用できる。
  • Unity Test Runner と NUnit の双方でテストできるので、時間のかかるテストで Unity Test Runner の完了を待っている間エディタを操作できなくなる問題大幅に緩和できる。
  • Unity でビルド可能なコードしか取り扱わないので、マネージプラグインやネイティブプラグイン特有の問題に煩わされることがない。

ただし、Unity に依存するコードは Unity でしかビルドできないので、基本的にコア言語機能と標準ライブラリのみで作れるものしか作れない(別途マネージプラグインやネイティブプラグインに依存する場合は別)。

使用可能な C# と .NET のバージョンは以下の通り。

Unity .NET C#
2021.1 4.6 相当 C# 8.0
2021.2 4.8 相当 C# 9.0
2021.3 4.8 相当 C# 9.0
2023.2 4.8 相当 C# 9.0

現状サポートのある一番古いバージョンは 2021.3 (LTS) なので基本的には .NET 4.8 、C# 9.0 を使えばよいだろう。(というか残念ながら Unity 6 でも .NET 4.8 相当・C# 9.0で 2021.2 から更新されていない)

.NET 4.X と .NET Standard の追加 API でしか使用できない API を使用すると Unity プロジェクトのプロファイル設定が .NET Standard の場合に使えない機能がでてくるので注意。

NuGet で取得できる NUnit3TestAdapter は .NET Framework でないと警告が出る(使えない?)ので .NET Standard ではなく .NET Framework を使用する。Unity で使えない API を誤って使わないように注意する(ここは運用でカバー)。

2021.1 以前の Unity をサポートしたい場合は .NET Framework 4.6.2、C# 8.0 で開発するとよいだろう。

dotnet CLI が生成するプロジェクトは、そのバージョンによって内容が変わるため注意する。

大前提として、以下の準備をしておく。

Unity Test Framework と NUnit のバージョンの対応関係は以下の通り。

Unity Test Framwork NUnit
2.0.1-exp.2 3.5
1.4 3.5
1.3.9 3.5
1.1.33 3.5
1.0.18 不明

NUnit 3.5.0 は何故かすべてのテストを強制的に実行してしまう (NUnit3TestAdapter のバージョンとの相性の問題?) ので、NUnit 3.14.0 を使用する

Visual Studio でプロジェクトのプロパティを変更しようとしてもメニューに表示されない場合があるので、生成した .csproj ファイルを手動で編集する必要がある。

プロパティ
TargetFramework net462 など
ImplicitUsings disable (または消す)
Nullable disable (または消す)

また ItemGroup の中で Using があった場合も Global Using が自動で追加されてしまうのでこれも消す。

-    <ImplicitUsings>enable</ImplicitUsings>
-    <Nullable>enable</Nullable>
+    <Nullable>disable</Nullable>
-  <ItemGroup>
-    <Using Include="NUnit.Framework" />
-  </ItemGroup>

Unity が .meta ファイルを自動生成しないように中間出力と出力を以下のように変更する。

+    <BaseOutputPath>.bin\</BaseOutputPath>
+    <IntermediateOutputPath>.obj\$(Configuration)\</IntermediateOutputPath>

また System.HashCode は Unity でも使えるので Microsoft.Bcl.HashCode は使っても良い。

結果として、プロジェクトの依存は以下のようになる。

<ItemGroup>
  <PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.1" />
</ItemGroup>

テストプロジェクトの依存は以下のようになる。

<ItemGroup>
  <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
  <PackageReference Include="NUnit" Version="3.14.0" />
  <PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
  <PackageReference Include="coverlet.collector" Version="6.0.2">
    <PrivateAssets>all</PrivateAssets>
    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
  </PackageReference>
</ItemGroup>