Unityでゲームを作っていると、C#スクリプトが増えたときに次のような問題が発生することがあります。
- C#スクリプトのコンパイル時間が長くなり、スクリプトを少し変更しただけで長時間待たされる
- スクリプト同士の参照関係がごちゃ混ぜになってしまい、例えばスクリプトを一部だけ別のプロジェクトに転用したくなったときに面倒なことになる
- ビルドするプラットフォームによってスクリプトを分けたいときに手間がかかる
こういった問題はゲーム開発において鬱陶しいので何とかしたいですよね。
そこで上記のような問題を解決するためにご活用いただきたいUnityの機能として「Assembly Definition(アセンブリ定義)」というものがあります。これを使えばUnityでありがちなイライラが一気に解消する可能性があるので、特にプログラマの方にはお勧めです。
ただ一方で注意点もあるのできちんと理解したうえで利用するのがよいと思います。そこでこの記事ではAssembly Definitionの概要や使い方・メリットや注意点を一通りご説明しますね。
Assembly Definition(アセンブリ定義)とは?
でははじめに「Assembly Definition(アセンブリ定義)とは何か?」という点を簡潔にご紹介しておこうと思います。
Assembly DefinitionはUnity2017あたりで導入された機能で、一言でいえば
のことです。例えばデフォルトだと、下の図のようにすべてのスクリプトが「Assembly-CSharp」というアセンブリに置かれます。
このデフォルトの状態は何も考えなくてよいため分かりやすい反面、C#スクリプトが増えるとコンパイル時間が長くなってしまう等の欠点があります。
そこでAssembly Definitionを使ってアセンブリを分割すると便利です。例えば下の図のようにアセンブリAとアセンブリBを作る場合…
Assembly-CSharpからスクリプトが抜き出されて、新しいアセンブリA・Bにそれぞれ分割されます。この場合アセンブリA内のスクリプトを変更するとアセンブリAだけが差分コンパイルされるので、分割前と比べるとコンパイル時間が短縮されます。
このようにAssembly Definitionはかなり地味な機能ではありますが色々なメリットがあるのが特徴です。
Assembly Definitionのメリットと注意点
ただAssembly Definitionはメリットばかりではなく、注意点もあるのでその辺もしっかりと理解して使う必要があります。メリットと注意点をまとめると次のようになります。
メリット
- スクリプト変更時のコンパイル時間が短縮される可能性がある
- スクリプト同士(というかアセンブリ同士)の参照関係を整理することができる
- どのプラットフォームでアセンブリを有効にするか指定できる
スクリプト変更時のコンパイル時間が短縮される可能性がある
まず一つ目のメリットは、先ほども書いた通りスクリプト変更時のコンパイル時間が短縮される可能性があることです。
もちろんプロジェクト内のC#スクリプトが少ないうちはそんなに変わりませんが、スクリプトが増えると明らかにコンパイルが速くなるので、大きなプロジェクトの場合はぜひAssembly Definitionを活用すべきだと思います。
スクリプト同士の参照関係を整理することができる
次に二つ目のメリットはスクリプト同士の参照関係を整理できることです。
例えばスクリプトの構成を次のようにする場合…
- 汎用スクリプト:特殊スクリプトから参照される場合がある
- 特殊スクリプト:汎用スクリプトを参照する場合があるが、汎用スクリプトからは参照できないようにしたい
通常だと何かの間違いで汎用→特殊の参照を作れてしまうかもしれません。しかしAssembly Definitionを使うと、アセンブリ同士の参照関係を制御できるので参照がごちゃまぜになるのを予防することができます(※)。こちらも一定以上の規模のプロジェクトで役立つメリットですね。
※ただし調子に乗って使いすぎるとアセンブリ同士の依存関係がゴチャゴチャして逆に分かりづらくなってしまうかもしれません。
どのプラットフォームでアセンブリを有効にするか指定できる
三つ目のメリットは、どのプラットフォームでアセンブリを有効にするかを指定できることです。Assembly Definitionのファイルをインスペクターで見てみると「Platforms」という設定項目があり、ここでそのアセンブリを有効にするプラットフォームを指定することが可能です。
特定のプラットフォームでのみアセンブリを有効化したい場合にはかなり便利だと思います。
注意点
- アセンブリ同士の参照関係は手動で設定する必要がある
- 分割したアセンブリとAssembly-CSharpとの関係性には注意が必要
アセンブリ同士の参照関係は手動で設定する必要がある
一つ目の注意点は、アセンブリ同士の参照関係は手動で設定する必要がある点です。
詳しい話は後述する使い方のところで説明しますが、アセンブリ同士に参照関係を持たせたい場合は一つ一つ手動で参照関係を設定しないといけないのでその点は少し面倒だと思います。
分割したアセンブリとAssembly-CSharpとの関係性には注意が必要
二つ目の注意点は、分割したアセンブリとAssembly-CSharpとの関係性には注意が必要だということです。
先ほど上の方で
という説明をしました。Assembly Definitionを使うということは、このAssembly-CSharpからスクリプトを抜き出して分割することなのですが、仕様として
- 「Assembly-CSharp」→「分割した他のすべてのアセンブリ」にはアクセス可能
- しかしその逆は不可能
という性質があります。つまり、例えばAssembly DefinitionでアセンブリAを分割したとすると、そのアセンブリAから元のAssembly-CSharpにはアクセスできなくなってしまうので注意しましょう。
Assembly Definitionの使い方
さて前置きが非常に長くなってしまい恐縮なのですが、ここから本題であるAssembly Definitionの使い方をご紹介しようと思います。
といっても上記の内容をご理解いただいていれば使い方は簡単なのでごく簡潔に説明していきますね。
新しいアセンブリ定義ファイルの作り方
まず新しいアセンブリ定義ファイルの作り方ですが、プロジェクトビューの何もないところで右クリック→「作成」→「アセンブリ定義」を選べばOKです。
なお、このとき「アセンブリ定義ファイルを作ったフォルダ以下のC#スクリプト」が新しいアセンブリに分割されます。つまり例えば「Assets/Scripts/Samples」内に新しいアセンブリ定義ファイルを作った場合、Samplesフォルダ以下に配置されているC#スクリプトが新しいアセンブリになるということです。
アセンブリ同士の参照関係の追加方法
次に分割したアセンブリ同士の参照関係の追加方法については、アセンブリ定義ファイルを見てみると「アセンブリ定義参照」という欄があるのでそこに必要な参照を登録すればOKです。
登録したら一番下の「適用する」ボタンを押すのを忘れずに。
ちなみにUnity公式のパッケージはそれぞれ個別のアセンブリに分割されているらしく、この欄に参照を登録することができます。上手く活用しましょう。
おわりに
以上、UnityのAssembly Definitionの概要や使い方についてご説明しました。
先ほども書いたようにAssembly Definitionはかなり地味な機能ではあるのですが、使いこなすことができれば非常に便利なのでお勧めです。ぜひ上記の内容を参考にしていただきコンパイル時間の短縮等にご活用いただければと思います。
この記事がUnityでのゲーム開発のお役に立てば幸いです。