シェーダーは GPU 上で実行する小さなプログラムであり、それらをロードするには時間がかかることがあります。個々の GPU プログラムは一般的にロードするのに時間がかかりませんが、シェーダーは、多くの場合、内部にバリアントがたくさんあります。
たとえば、スタンダードシェーダー 。完全にコンパイルされると、結局、わずかに異なる何千もの GPU プログラムになります。これによって 2 つの問題の可能性が発生します。
ゲームをビルドしている間、Unity は、内部シェーダーバリアントのいくつかがゲームで使用されていないことを検出し、ビルドデータからそれらをスキップします。ビルド時間の削減は、以下のために行われます。
#pragma shader_feature
を使うシェーダーのための個々のシェーダーの機能。ある特定のバリアントが使用中のどのマテリアルにもまったく使用されない場合、そのバリアントをビルドに加えません。内部シェーダーバリアント に関するドキュメントを参照してください。ビルトインシェーダーのうち、スタンダードシェーダー は、内部シェーダーバリアントを使用しています。上記の組み合せは、シェーダーデータサイズをしばしば大幅に減らします。例えば、完全にコンパイルしたスタンダードシェーダーは数百メガバイトを消費することもあります。しかし、典型的なプロジェクトでは、大抵、わずか数メガバイトを消費します (アプリケーションのパッケージングプロセスによってさらに圧縮されることもよくあります)。
すべてのデフォルト設定で、Unity は、ShaderLab シェーダー オブジェクトをメモリへロードしますが、実際に必要になるまで、内部のシェーダーバリアント を作成しません。
これは、ゲームのビルドに含まれているシェーダーバリアントはまだ使用可能であることを意味します。ただし、それらが必要になるまでメモリやロード時間のコストはかかりません。例えば、シェーダーには常に影を持つポイントライトを処理するためのバリアントが含まれていますが、ゲーム内の影にポイントライトを使わない限り、この特定のバリアントはロードされません。
このデフォルトの動作の欠点の 1 つは、いくつかのシェーダーバリアントが初めて必要になるときに、しゃっくりが起こる場合があることです。- 新しい GPU プログラムコードがグラフィックスドライバーにロードされなければならないからです。これはゲームの間は好ましくないので、Unity には それを解決するための ShaderVariantCollection アセットがあります。
シェーダーバリアントコレクションは 1 つのアセットで、基本的に シェーダー のリストです。各シェーダーに関して、パスの種類と起動のためのシェーダーキーワードの組み合わせを表示します。
実際に使用したシェーダーとそのバリアントに基づいてアセットの作成を支援するために、エディターは実際に使用されているシェーダーとそのバリアントを追跡することができます。Graphics Settings に、現在追跡されているシェーダーから新しいシェーダーバリアントコレクションを作成するボタンと、現在追跡しているシェーダーリストを削除するボタンがあります。
ShaderVariantCollection アセットを取得したら、これらのバリアントをアプリケーションのロード中に自動的にプリロードされるか (Graphics Settings の Preloaded Shaders の下) 、スクリプトから個々のシェイダーバリアントコレクションをプリロードすることができます。
Preloaded Shaders リストは、頻繁に使用されるシェーダーを対象としています。ここにリストされているシェーダーのバリアントは、アプリケーションの生存期間にわたってメモリに読み込まれます。これによって、多数のバリアントを含む ShaderVariantCollections アセットに著しい量のメモリが使用される場合があります。これを避けるには、ShaderVariantCollection アセットをより細かく作成し、スクリプトから読み込む必要があります。1つの方法としては、各シーンに使用されているシェーダーバリアントを記録し、別々の ShaderVariantCollections アセットに保存し、それらをシーン起動時に読み込むことです。
ShaderVariantCollection スクリプトクラスを参照してください。