【Unity】プロジェクトに不要なアセットをプロジェクトから退避するエディタ拡張を作ってみた
追記:Unity 2017で動作しない不具合があるかもしれません。現在確認中
Unityのプロジェクトには様々なアセットが含まれます。そういったアセットの中から「ゲームの進行に必要な最低限のアセット」を残しプロジェクト外へ退避するアセットを以前に自作してみました。
これの続きです。
得られる効果
効果としては「コンパイル時間の短縮」「HDD容量の節約」「プラットフォーム切り替え時間の短縮」「不要なファイルを消してプロジェクトをシンプルに」「ゲーム再生時の待ち時間が短く」「エディタが少し軽くなる」等々の効果が期待できるといえば出来ます。
未使用アセットをUnityプロジェクトから退避する奴、シェーダーとエディタ拡張もちゃんと動作するようになった pic.twitter.com/jqbPSoCrkD
— 椿 (@tsubaki_t1) 2015, 7月 24
機能
例えばAssetStoreには必ずDemoシーンを含める事が必要ですが、Demoシーンの内容が必ずしもゲームに必要とは限りません。とはいえDemoシーンが使用しているコードがどこまで不要でどこまで必要なのかは判断が難しい所です。
なので、必要な部分の実装が終わったら、関係ない所は全部プロジェクト外にしまっちゃおう…といったものがコレのコンセプトです。
コードをストリップする意味
コードをストリップするのはIL2CPPへの変換時間短縮と、Monoのコードストリップよりアプリサイズを縮小するのが目的です。ついでにゲーム再生時の停止時間が若干短くなったりします。
(まぁジェネリックとかLINQ使いまくってるプロジェクトにはあまり効果がないかもしれませんが)
IL2CPPのコードストリップと比較するとそこまで小さくはなりませんが、Monoの持っているストリップよりは(場合によっては)ストリップしてくれると思います。
退避はunitypackageで行うので、uuidが維持されるため、必要になれば元の環境に戻すこともだいたい可能です。
試しに実行してみる
試しにUnityの新しい2P対戦戦車ゲーのチュートリアルであるTanks!に実行してみると、使っていないImageEffectやImageEffectのシェーダーこれから編集する予定の(現在未使用な)サンプルコードが不要なアセットとして検出されます。
これの機能「Unityがゲームに使用しているファイル以外は全て退避する」は正確に言えば
「ゲームに含まれるシーンが参照しているアセット」「シーンが参照しているアセットが参照しているアセット」「シーンが参照しているアセットが参照しているコード」「シーンが参照しているアセットが参照しているコードが参照しているコード」「シーンが参照しているアセットが参照しているコードを参照しているエディタ拡張」「シーンが参照しているマテリアルが参照しているシェーダー」「シーンが参照しているマテリアルが参照しているシェーダーが参照しているシェーダー」「Resourcesフォルダ以下にあるアセットが参照しているアセット」「Resourcesフォルダ以下にあるアセットが参照しているコード」「Resourcesフォルダ以下にあるアセットが参照しているコードが参照しているコード」「StreamingAssets以下のファイル」「Plugins以下のファイル群」(中略)
といった感じに、参照マップを構築し、最終的にゲームに含まれるアセットを残して、他のアセットはunitypackageとして出力する機能を持っています。
参照関係はXMLにキャッシュ
ちなみに出力したアセットの関係図はxmlとして出力し、2回目以降はファイルの内容に変化がない限りは参照マップの再計算は行わないようにしています。
それとjsは非対応です。
エディタのコードがファイルパスで参照している場合は追えないので、退避されないように注意してください。エクセルデータとか。
使い方
導入はhttps://github.com/tsubaki/UnityAssetCleaner/blob/master/cleaner.unitypackage?raw=trueをダウンロードし、インポートします。
UIの説明
Window > Delete Unused Assetsから必要な物を選択します。
only resources : リソースとシェーダーのみを退避します。最も安全です。
unused by editor : 未使用のスクリプトとリソースを退避します。ただし、残っているスクリプトを拡張しているエディタ拡張、およびエディタ拡張が参照しているスクリプト、MenuItemを持つスクリプトは残ります。
unused by game : ゲームに不要なコードは全部消します。
まずはリソースのみのストリップがおすすめ
unused by editorやunused by gameは自分の把握していない条件で余計なコードを削除する可能性があるので、チェックを簡単にするためonly resourcesを実行してから実行するのをお勧めです。
それにコードは自前で解析してる部分が結構時間かかるので、その点も含めてリソースだけでも先に計算しちゃうのが良さそうです。
また、リソースのインポート時間がかかってはコレを行う意味があまりないので、メニュバー>Edit> Preference で設定画面を表示し、Compress Asset on Importのチェックを外しインポート直後に変換が走らないようにしとくと良さそうです。
指定フォルダ内のみチェック
もう一つ、フォルダを右クリックしDelete unused assets > unused only resourcesを選択すると、該当フォルダ内の不要リソースを破棄します。
キャッシュをクリア
上手く動かなくなったら(参照されてないのにリストに計上されない)キャッシュをクリアしてください。
メニュー > Window > delete unused > clear cache
ストリップ後に不具合が出たら
またファイルを大量に削除した際、monodevelopが異常に重くなったりUnityが存在しないクラスでコンパイルエラーを起こしたりする事があります。その場合はMonodevelopとUnityエディタを再起動してください。
AssetBundleは見てません。無視リストを作る予定でしたが、現状ついてません。要望があればつけようかなと思います。
次の予定
正直こんな面倒な事しなくとも「参照マップを構築し、ゲームに関係ある変更があったファイルとその関係ファイルのみを抽出しコミット、その後に不要なファイルはバージョン管理を使って破棄」でよくね? って思ってしまったので、多分そっちの方向に進みます。
コード解析はUnityのエディタ拡張でやってますが、別に独立したアプリケーションでも問題ないので、そっちに移します。そっちならMono.Cecilと干渉しなさそうですし。
あとはアセットの参照マップをビジュアライズするのも面白いかもしれませんが、プロジェクトが大規模になると個々の関係性を見ていくのは大変になっていくので、どうしようか考えます。