[Unity] 対象のフォルダ以下にあるファイルの名前一覧をもつクラスを生成する拡張

# 記事の内容のプロジェクト（Unlicense）
https://github.com/ttyyamada/GenerateUnityFileList

# はじめに
この記事ではEditor拡張を使って、対象のフォルダ以下にあるファイルのリストを出力するクラスを作成するものを作っています
ファイルのリストを作成する理由としては、AssetBundle化した場合などにファイルの名前でアクセスすることが多いのですが
その指定が文字列を直接指定していた場合、ファイルの移動やリネームをしただけで動かなくなってしまうことがあります

そこで変数に入れて参照することで、そういったエラーを防げますし、ファイルの読み込みテストも容易にできます。

今回作ったものは全てGithubにUnlicenseで上げておりますので、ご自由にお使いください

## 22/08/31 Dictionaryでの出力に対応しました！
![スクリーンショット 2022-08-31 15.59.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49946/da711240-b01c-f874-daee-4e5ae8ec55de.png)

Dictionaryでやるか、変数で出力するかを選べるようになりました
また、細かいですが生成タイプ、ファイル名、namespace名、クラス名は生成後保存されるようになりました

# 動作
作成した拡張の動画です。このような形でファイルが出力されます
![GenerateFileList.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49946/06612742-eec1-5145-812c-ee2e5cb1f26c.gif)

コードは全て上げていますが、どのようにしてファイルのリストを作っているのか。のポイントを書いていきます

# ファイルのリストの取得
まず、特定フォルダ以下にあるファイルの取得です。これは実はすごく簡単で、
[AssetDatabase.GetAssetOrScenePath](https://docs.unity3d.com/jp/current/ScriptReference/AssetDatabase.GetAssetOrScenePath.html)
を使い、Editor拡張でアタッチしたフォルダのパスを取得しています

その後
[DirectoryInfo.GetFiles](https://docs.microsoft.com/ja-jp/dotnet/api/system.io.directoryinfo.getfiles?view=net-6.0)
を使い、サブフォルダを含めるかどうかでファイルのリストを取得しています

ただ、このファイルのリストを全て使うと、metaファイルなどのリスト化したくないものまでリストに入ってしまいます

## ファイルのリストから特定の拡張子を除外
今回はとりあえず4つの拡張子をリストから除外するようにしました
[_ignoreExtensionList](https://github.com/ttyyamada/GenerateUnityFileList/blob/main/Assets/GenerateFileNameList/Editor/Script/GenerateFileList.cs#L18)に持たせています。
対象としたのは`".meta", ".txt", ".DS_Store", ".cs"`の4つです
目的がアセットのリストなのですが、必要に応じて増やしていくと思います
ファイルのリストを作成する際に、拡張子をチェックしてこれらに該当していたら除外しています

## ファイルの名前から相対パスを取得
実は今回一番苦労したのがここになります。
[AssetDatabase.GetAssetOrScenePath](https://docs.unity3d.com/jp/current/ScriptReference/AssetDatabase.GetAssetOrScenePath.html)で取得したパスは`Assets/`から始まるプロジェクトからのパスなのですが、[DirectoryInfo.GetFiles](https://docs.microsoft.com/ja-jp/dotnet/api/system.io.directoryinfo.getfiles?view=net-6.0)で取得したファイルのパスは絶対パスになっていました
今回は設定したフォルダからの相対パスを出したいので、変換する必要があります
リファレンスを探しましたが、なかなかに見つからず、力わざでやることにしました（コメントお待ちしています）

対象となるのはこの部分です
[プロジェクトのルートパス以外を削除](https://github.com/ttyyamada/GenerateUnityFileList/blob/main/Assets/GenerateFileNameList/Editor/Script/GenerateFileList.cs#L134)
まず[Application.dataPath](https://docs.unity3d.com/ja/2020.3/ScriptReference/Application-dataPath.html)でプロジェクトのパスを取得します。
そのパスにはプロジェクトのルートである　`Assets/`が入ってしまっているので、`'/'`でsplitをし、最後のパスである`Assets/`を外したパスを作成します

その後、ファイルの絶対パスから作成したパスを除外し、さらにその後に探索するフォルダの相対パスを除外することで、探索するフォルダからの相対パスが取得できました

## csファイルの出力方法
これは単純にcsファイルのテンプレートを用意し、必要な部分をReplaceしていきます
[NameListsTemplate.txt](https://github.com/ttyyamada/GenerateUnityFileList/blob/main/Assets/GenerateFileNameList/Editor/Resources/NameListsTemplate.txt)
を用意し、そこでnamespace名、クラス名、それとファイルのリストに使うテンプレート行を用意します

今回は `#`で囲われている部分をReplace対象にしましたが、ここはなんでもいいです
ファイルのリストに関しては一括での置き換えが難しいので、対象の行となる部分を変数としてあらかじめ持っておきます
[FileListTemplate](https://github.com/ttyyamada/GenerateUnityFileList/blob/main/Assets/GenerateFileNameList/Editor/Script/GenerateFileList.cs#L40)
このテンプレート一個一個に対してファイル名をもとにリストをつくっていき、最後にそのリストをFileListTemplateでReplaceすることで一括でのリストを作成しています

（変数名に使えないファイル名だとエラーが出ますが、現在は空白のみ対応しています）

禁則文字や別フォルダにある名前被りなどは出てくるとは思いますが、それらは発生したら対応する。というアプローチでいいかと思います

出力するテキストファイルが完成したら、最後に指定したファイル名で出力して完成です
[出力処理](https://github.com/ttyyamada/GenerateUnityFileList/blob/main/Assets/GenerateFileNameList/Editor/Script/GenerateFileList.cs#L163)

## 拡張の使い方の説明
最後に拡張のGUI部分の解説をします。そのままではありますが、念の為。ちなみに全部の項目が設定必須です
![GenerateFileList.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49946/50b59902-8a16-e7f7-fedc-b3d3d6b93a65.gif)

1. 検索フォルダ<dd>検索の対象となるフォルダです。この配下のファイルをリスト化します</dd>
1. ファイル名<dd>アウトプットするcsファイルのファイル名です。拡張子は不要です</dd>
1. namespace名<dd>使用するnamaspaceを指定します</dd>
1. クラス名<dd>使用するクラス名を指定します</dd>
1. 成績先フォルダ<dd>クラスファイルを生成する親フォルダを指定します</dd>
1. サブフォルダを含める<dd>階層になっているフォルダがあった場合、その中身も含めてリスト化します</dd>

## 最後に
こういったファイルのリストを作る拡張は一度作っておくと使いまわせますし、ファイルの消失などの事故も防ぎやすいです
また、重複しているファイルのチェックなどもしやすくなるので、機械的にこういった処理を行えると大変便利ですので
最初に一手間をかけて今後の開発を快適にしていくことを心がけると、いい開発ができるのでは。と思っています

今回記事で紹介した内容は全てGithubに上がっており、Unlicenseになっていますので、ぜひ使っていただけると幸いです

ありがとうございました