【Unity】存在するはずのDLLが参照されずGameCIが失敗する場合の対処法

# 初めに

[GameCI](https://game.ci)はUnityプロジェクトのビルドをCI/CDツールで自動化するためのツール群です。
Unityのビルド環境として使えるDockerイメージ（`gameci/builder`）やUnityのビルド周りのタスクを実行するためのGitHub Actions等を提供しています。

これを使用して自前のUnityプロジェクトのビルドを自動化しようとした際に、ローカル環境では問題なくビルドできるのに、GameCIではなぜかビルドエラーになってしまう現象に遭遇したので、その内容と対処方法を記載しておきます。

以降、GameCIのGitHub Actionsを使用している場合を含め、GameCIのDockerイメージを使用することを「GameCI上で」と記載します。

## 現象

ローカルではビルドできているのにも関わらず、GameCI上では名前空間が存在しないという内容のエラーでビルドに失敗してしまいます。
こんな感じのエラー文で……

```log
"/opt/unity/Editor/Data/NetCoreRuntime/dotnet" exec "/opt/unity/Editor/Data/DotNetSdkRoslyn/csc.dll" /nostdlib /noconfig /shared "@Library/Bee/artifacts/1900b0aE.dag/Mirror.rsp"Assets/Mirror/Runtime/Transport/FizzyFacepunch/FizzyConnectionManager.cs(1,7): error CS0246: The type or namespace name 'Steamworks' could not be found (are you missing a using directive or an assembly reference?)
Assets/Mirror/Runtime/Transport/FizzyFacepunch/FizzyFacepunch.cs(1,7): error CS0246: The type or namespace name 'Steamworks' could not be found (are you missing a using directive or an assembly reference?)
Assets/Mirror/Runtime/Transport/FizzyFacepunch/FizzySocketManager.cs(1,7): error CS0246: The type or namespace name 'Steamworks' could not be found (are you missing a using directive or an assembly reference?)
Assets/Mirror/Runtime/Transport/FizzyFacepunch/FizzySocketManager.cs(2,7): error CS0246: The type or namespace name 'Steamworks' could not be found (are you missing a using directive or an assembly reference?)
```

私の環境ではSteamworks APIのC#向け実装である[Facepunch.Steamworks](https://github.com/Facepunch/Facepunch.Steamworks)を使用しており、そこで定義されている`Steamworks`名前空間が見つからないという内容でした。しかし、その名前空間が定義されているDLLは確実にプロジェクト上に存在しており、ビルド対象のプラットフォームに対して有効化されていました。

## 発生条件

以下のすべてがそろった時に発生します。

- GameCIのLinux向け`gameci/editor`Dockerイメージを使用している
    - GameCIの[Unity - Builder (GitHub Actions)](https://github.com/marketplace/actions/unity-builder)でRunnerをLinux系（`ubuntu-latest`等）にしている場合も同様
- ビルド対象プラットフォームをLinux以外（WindowsやMacOSX）にしている
- 使用しているManaged DLLが、ビルド対象プラットフォーム向けにはインポートされているがLinux向けにはインポートされていない

## 原因

Linux用Unity Editorが、ビルド時にビルド対象プラットフォームに関わらずLinux向けManaged DLLを参照することが原因です。（具体的な公式の文献は見つかりませんでしたが）

GameCIは、Linux系Dockerイメージで実行された場合に（当然ですが）Linux用Unity Editorを使用します。
対象プラットフォームがWindowsやMacOSXであっても、上記の理由からビルド時にはLinux向けManaged DLLが参照されます。
ここでLinux向けManaged DLLがインポートされていない場合、そのDLLで定義されている名前空間等は参照できないのでエラーになります。

ローカル実行時にWindowsやMacOSX用Unity Editorを使用しており、その環境向けのManaged DLLがインポートされている場合はエラーなくビルドできるため、ローカルではビルドできるのにGameCI上ではビルドできないという状態になっていました。

## 対処法

以下のどちらかで対処可能です。

- Windows/MacOSX向けDockerイメージを使用する
    - GitHub Actionsの場合はWindows/MacOSX系Runnerを使用する
- Linux用のManaged DLLを用意する

後者について、提供元のLinux向けManaged DLLがあればそれをインポートすればよいです。
存在しない場合、Linux向けに使えそうなManaged DLLがあればそれをコピーしてLinux用に設定すると解決できるかもしれません。
それも無理そうならソースコードからコンパイルするとかがんばってLinux向けManaged DLLを用意するか、OSSならPRを出してみるとか……

私の環境で原因となった[Facepunch.Steamworks](https://github.com/Facepunch/Facepunch.Steamworks)の場合はPOSIX向けDLLがMacにのみ設定されている状態だった[^1][^2]ため、コピーを作成してLinux向けに設定することで対処できました。

## 参考文献

- https://discord.com/channels/710946343828455455/710946344264794219/946975481775939654 （GameCIのDiscordサーバーに入らないと見れません）

[^1]: https://answers.unity.com/questions/1778267/cannot-use-facepunch-steamworks-library.html
[^2]: https://github.com/Facepunch/Facepunch.Steamworks/issues/645