Unityで使用するdllファイル(C#)を、Visual Studio 2022でクラスライブラリ(C#)として作成する方法を説明します。「Unityで使用するdllファイル(C#)の作成」で、Unityでの「Windows.Foundation.UniversalApiContract」の参照不可のエラーが発生して、実行できませんでした。今回も実行はできませんでした。このため、アドバタイズメントスキャンはあきらめました。

・Unity: Unity 6 (6000.3.2f1)
・Visual Studio 2022

Visual Studio 2022によるプロジェクトの作成

Visual Studio 2022を起動し、「新しいプロジェクトの作成」をクリックし、次のようにC#クラスライブラリを選択します。

表示された「新しいプロジェクトを作成します」ダイアログでプロジェクト名を「TestScan2601」とし、次の「追加情報」ダイアログでフレームワーク「.NET Standard2.1」を選択し、新規プロジェクトを作成します。

フレームワーク「.NET Standard2.1」を選択できるC#クラスライブラリを必ず選択します。

UnityEngine.DLLの参照設定

Unity(Editor Ver:6000.3.2f1)のUnityEngine.DLLとUnityEngine.CoreModule.dllは、「6000.3.2f1\Editor\Data\Managed\UnityEngine\」に置かれています。

参照するためには、Visual Studio 2022のソリューションエクスプローラーの依存関係を右クリックし、「プロジェクト参照の追加」を選択して、置かれたUnityEngine.DLLとUnityEngine.CoreModule.dllを選択します。

正常に参照できると、次のように参照設定の表示に、「UnityEngineとUnityEngine.CoreModule.dll」が追加されます。

「参照」と「依存関係」の違い
基本的には同じ役割(そのプロジェクトが動くために必要な外部ライブラリの指定)ですが、プロジェクトの種類によって表示が異なります。

「参照」と「依存関係」の違い
プロジェクト形式 表示名 特徴
.NET Framework (旧形式) 参照 直接 .dll ファイルを指定して追加するスタイル。
.NET Standard / .NET 6+ 依存関係 DLLだけでなく、NuGetパッケージやプロジェクト間参照を階層構造で管理するスタイル。

C#側チェックアプリの作成

C#クラスライブラリで作成したC#側チェックアプリを次に示します。

TestScan2601

using UnityEngine;

namespace MyLibrary  // ← この名前が重要!
{
    public class MyPlugin // ← publicがついているか確認!
    {
        public static void Hello()
        {
            Debug.Log("DLLからこんにちは!");
        }
    }
}
  • MyPluginクラスに、継承のための「: MonoBehaviour」を付けない。これにより、new で自由にインスタンス化でき、Unityのライフサイクル(StartやUpdate)に縛られず、純粋なC#ライブラリとして動作します。
  • ・UnityEngine.CoreModule.dll というファイル名であっても、コード内で使う名前空間は UnityEngine.CoreModule ではなく、単なる UnityEngineとなります。なお、Debug.Log は UnityEngine.CoreModule.dll というファイルの中に定義されています。
  • namespaceは付与できます。Unity側でusing宣言を使って参照させます。

上記のコードをビルドして、dllファイルを作成します。

dllファイルをUnityへ登録

作成された「TestScan2601.dll」を、次のようにunityのProjectのAssetsにトラッグします。

表示された「TestScan2601.dll」をクリックすると、次のように表示されます。

参考:DLL のインポート設定の確認
Unity 上で DLL ファイルを選択し、以下の設定を行います。

  1. Auto Reference: チェックを入れます。
  2. Validate References: チェックを外します(これ重要です。Unity が DLL の整合性をチェックする際に、不要な Editor 参照を探しに行くのを防ぎます)。
  3. Platform settings: Any Platform のチェックを外します。すべてチェック
  4. Apply を押します。

画像を見ると、「Assembly Info: Targets .NET 4.x」になっているが、「.NET Standard 2.1」になりません。

Unity で.NET Standard2.1 を使用する

「Edit」→「Project Setting」を選択します。

表示されたダイアログで、「Player」→「Configuration」→「Api Compatibility Le..」を選択して、「.NET Standard2.1 」を選択します。

Unityのサンプルコードの作成

作成したUnityのサンプルコードを次に示します。

TestScan2601 .cs

using UnityEngine;
using MyLibrary; // ここでエラーが出る場合、まだDLLが認識されていません

public class TestScan2601 : MonoBehaviour
{
    void Start()
    {
        // 名前空間を直接指定して呼び出す方法を試す
        MyLibrary.MyPlugin.Hello();
    }
}

作成した「TestScan2601 .cs」を「main camera」にドラッグ&ドロップします。

UnityでスクリプトがMain Camera(あるいは他のGameObject)にドラッグ&ドロップできない場合、主に「プログラム上のエラー」か「ファイル名とクラス名の不一致」を確認します。

Unityでの実行結果

Unityで実行すると次のメッセージがConsolsタブに表示されます。

「Windows.Foundation.UniversalApiContract」の参照不可のエラー

Unityで使用するdllファイル(C#)の作成」で作成したアドバタイズメントスキャンアプリを実行すると、前回と同様な次のようなエラーが発生します。

FileNotFoundException: Could not load file or assembly ‘Windows.Foundation.UniversalApiContract, Version=20.0.0.0, Culture=neutral, PublicKeyToken=null’ or one of its dependencies.
TestScan2601Unity.Start () (at Assets/TestScan2601Unity.cs:9)

原因
コード内でWindowsの標準API(スキャナーやBluetooth、ファイルシステムの一部など)に触れようとしている場合、Unity(特にMonoランタイム)はそれらの参照を自動で解決できず、実行時にエラーとなります。

Windows.Devices.Bluetooth は UWP (Universal Windows Platform) 固有の API であり、通常の .NET Standard 2.1 のクラスライブラリでは Unity 実行時に参照を解決できません。

解決方法
Unity で Windows の BLE(Bluetooth Low Energy)機能を直接 DLL から叩くには、以下のいずれかの対応が必要となります。

  • Windows 固有 API を使うには、プロジェクトファイル (.csproj) に Windows SDK のメタデータを参照させる必要があります。
  • Unity が DLL 内の Windows API を認識できるように設定を調整します。
  • DLL ではなく Unity 内部で C++/WinRT を検討します。

Unity 側でのクリーンアップ

次のようにAssembly-CSharp-Editor に関するエラーがで続けている場合、Unity 6 の「Burst コンパイラ」が、DLL の中身をスキャンする際に、古いキャッシュや間違った依存関係を参照しているのが原因と考えられます。

Failed to find entry-points:
Mono.Cecil.AssemblyResolutionException: Failed to resolve assembly: 'Assembly-CSharp-Editor, Version=0.0.0.0, 
Culture=neutral, PublicKeyToken=null' ---> System.Exception: Failed to resolve assembly 'Assembly-CSharp-Editor, 
Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'

この場合次のクリーンアップ操作を行い、DLL の中身をスキャンする際に古いキャッシュや間違った依存関係を参照しないように修正します。

1. Burst のキャッシュの完全な削除

ログに Burst.Compiler が出ているため、Burst が以前の(失敗したときの)依存関係を覚えています。

  1. Unity エディタを閉じます。
  2. プロジェクトフォルダ内の Library フォルダ を削除します。
  3. さらに、以下のフォルダがあれば削除します。
  4. ・Temp フォルダ
    ・obj フォルダ(もしプロジェクト内にある場合)

  5. Unity を再起動します。