【Unity】とりあえずAssemblyDefinitionFilesを使ってみる

# はじめに
この記事は[Hamster Output Advent Calendar 2024](https://qiita.com/advent-calendar/2024/game_hamster)の17日目の記事です！

本記事はとりあえず、AssemblyDefinitionFilesの使い方を簡単に書いた記事です。名前だけ聞いたことがある方や、気になってるけど使い方が分からない方はぜひ...自分も最近使い始めたばかりなので、詳細に詳しいわけではありませんが...

# 参考にしたリンク

https://tsubakit1.hateblo.jp/entry/2018/01/18/212834

https://kingmo.jp/kumonos/unity-assembly-definition/#index_id3

# 何ができるか
#### ・どこからでも参照ができなくなる
Unityでクラスを作ると、どのクラスからでも参照することができますがAssemblyDefinitionを利用すると、参照を明示的に設定する必要があるので、知らない間にチームメンバーにクラスを参照される...っていう事故を減らせます。(場合によるかも...?)

#### ・循環参照ができなくなる
AとBというクラスがあった時に、AがBを参照して、BがAを参照するみたいなことを循環参照とか言ったりしますが、AssemblyDefinitionを利用するとこれができなくなります。

#### ・コンパイルが早くなる(実はあまり分かっていない)
↓　Unityでのこれが多少早くなるらしいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/cfe59685-4633-87bd-ff10-df5346e0f5f5.png)

# とりあえず使ってみる

### ・準備と確認
AppleとHumanのフォルダーを作ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/daadbae5-11d4-6e15-6ae5-f330695b40de.png)

作ったフォルダーにAssemblyDefinitionをそれぞれ作ります。Create → Scripteing → AssemblyDefinition

今回、名前はフォルダーと同じ名前を付けました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/a352c3ea-0d62-acd2-f10a-0a95e11a538a.png)

そして、AssemblyからAutoReferencedの設定を外します。この設定をオフにすると毎回コンパイルする対象から外れるのと、AssemblyDefinitionを設定していないクラスからの参照ができなくなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/9a6ee69f-fdcd-d010-33d2-d1b3b9953637.png)


ついでに、AppleとHumanのMonoBehaviourのスクリプトを作り、中にpublicメソッドのLogを用意します。HumanもAppleと内容が一緒です。
```C#
public class Apple : MonoBehaviour
{
    private void Start()
    {

    }

    public void Log()
    {
        Debug.Log("Apple");
    }
}
```

ここまでできたら、AppleクラスからHumanクラスを参照して見ようと思います。名前を入力して検索一覧を確認するとHumanが存在しないことが分かります。つまりどこからでも参照できた...というのができなくなっています。もちろんHumanからAppleを探しても同じ内容になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/21bf1c9e-1b13-3c3d-a2bd-a22d27ad471c.png)

### ・参照してみる
AppleのAssemblyDefinitionをクリックしてインスペクタから参照の設定を行います。Assembly Definition Referenscesという項目の＋をクリックしてHumanのAssemblyDefinitionを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/7a3d314e-0dae-51bd-87be-1e6ae2edf37d.png)

最後に、下側にあるApplyを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/42d8887c-7de3-9cf7-0ade-cb174c834107.png)

そして、Appleクラスからもう一度Humanを参照して見ると...検索一覧にHumanクラスが表示されるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/385d3ab5-d61f-e08f-b579-6669aa954aac.png)

GUIから参照の設定を行う必要があるので少し手間がかかりますが、参照している部分が分かるようになる利点もあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/92cba14d-69cc-65e4-b9d1-ded184ed4a10.png)

### ・循環参照をするとどうなるか

先ほどAppleのAssemblyDefinitionでHumanを参照したようにHumanからAppleを参照して見たいと思います。そうすると下のエラーが出てきます...


:::note alert
こんな感じのエラーが出ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/71b41f44-cd99-b4c0-48f4-b9435edd1575.png)
:::

翻訳すると循環参照するな！というエラーが出てますね。Humanか、AppleのどちらかのAssemblyから片方の参照を消せばこのエラーは解決できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/022577d4-6fc8-1464-f7b1-5fbf283f2e2d.png)

### ・internalアクセス修飾子の出番もある
Assemblyを切り分けるとinternalというアクセス修飾子が効力を発揮するようになります。Assemblyの参照を行うと、そのファイルの中にあるクラスを全て参照することができますが、internalをつけると、同じファイル内の参照であれば、public、違うファイルからの参照だとprivateになるということができるので、参照させたいクラスを決めることができます。

例えば、Humanクラスのアクセス修飾子をpublicからinternalに変えると、
```C#
internal class Human : MonoBehaviour
```
Appleクラスから参照することができなくなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/e91b83e9-862d-b8c2-8e33-4c2b2ab24869.png)

### ・namespaceの設定
RootNamespaceに名前を付けると、クラスを作成した時に自動でnamespaceを追加してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/a3575785-0b7e-dd4c-4717-5e4716ecd8f6.png)

### ・デメリット
UIやInputSysytemなど、今まで使ってた機能を参照する時にAssemblyを設定する必要があるのでこの部分はかなり面倒です。

ゲーム開発で使う場合、○○がない...？あれ？見たいなヒューマンエラーがよく起きます。

Assemblyを分けすぎると地獄を見る

Assemblyを分けていないクラスからアクセスできなくなる

# どんな時に使うべきか
チームでゲーム開発をする時に参照関係や依存関係を考えたい時とかがおすすめです。

いきなり開発に入れると躓くと思うので、事前に少し触ってから導入することをおすすめします(一敗)