こんにちは、エンジニアのオオバです。
Unityでオブジェクトを思ったとおりの見た目にするためにシェーダーを皆さん書いていると思います。
複雑なシェーダーになればなるほどGPU負荷が上がっていきスパイク(カクつき)の原因になります。
そこで本記事ではシェーダーのプロパティアクセスを2.5倍早くなるテクニックを紹介していきます。
シェーダーをガリガリ書いている方はぜひ読んでみてください。
👉DOTweenの教科書を読んでUnityアニメーションをプログラミングしてみよう!
シェーダーのプロパティにアクセスとは?
シェーダーはマテリアルを通してシェーダー内のパラメーターを更新することが可能です。
- 数値
- 色
- テクスチャ
など。
さまざまなシェーダー内のパラメータをC#を使って変更できます。
// シェーダー内の_Propパラメーターに100を代入
material.SetFloat("_Prop", 100f);
たとえば上記のソースコードはマテリアルにセットされたシェーダー内の「_Prop」パラメーターに100を代入したということになります。
文法の内訳は以下です。
第1引数 | 第2引数 |
---|---|
シェーダー内の変数名 | 代入する値 |
このようにシェーダーのパラメーターを変更して見た目を変更することはよく発生します。
関数 | 更新する値の種類 |
---|---|
SetInteger | 整数 |
SetFloat | 浮動小数点 |
SetTexture | テクスチャ |
SetColor | 色 |
SetVector | Vector4 |
SetMatrix | 4x4行列 |
SetFloatArray | float型配列 |
「SetFloat」以外にも値をシェーダーのパラメータを変更する関数が実装されています。上記の表以外にもまだまだあります。
↓詳しくは公式リファレンスを確認してみてください。

シェーダーパラメーターの文字列アクセスは重い
ここからが本題ですが、前章で紹介したシェーダーのパラメーターアクセス方法は処理としては重いです。言い換えるともっと効率的なアクセス方法があります。
それは 「PropertyToID」 です。
PropertyToIDとはシェーダー内の変数名をIDに変換してIDでパラメーターにアクセスする手法です。
具体的には次のコードでパラメーターを文字列からIDに変換します。
int id = Shader.PropertyToID("_Prop");
Shaderのクラスメソッド PropertyToID
を使うとint型の値が返ってきます。
この値を使ってシェーダーパラメーターにアクセスするのです。IDを使ったシェーダーアクセス方法はこちら。
material.SetFloat(id, 100f);
文字列の時と文法に変更はありません。 文字列が整数に置き換わっただけ です。
文字列からIDに変更するだけでパフォーマンスが向上します。
PropertyToIDはどのくらいパフォーマンスアップするのか
では「PropertyToID」が実際どのくらいパフォーマンスを上げるのか確認していきましょう。
確認方法は次の検証コードとUnity Profilerを使用して計測します。
toggleを切り替えて文字列参照と整数参照を切り替えてプロファイルします。
上の動画はUnity Profilerの画面です。toggleを切り替えると、明らかなパフォーマンスの違いが出ました。
文字列指定 | ID指定 |
---|---|
4.47ms | 1.61ms |
ID指定の方が約2.5倍パフォーマンスが良いという結果になりました。
プロファイラーでPropertyToID処理の中身を確認
なぜPropertyToIDの方が処理速度が早くなるのか確認してみましょう。
Unity Profilerで確認すると両者には処理内容に大きな違いが生まれていることが分かります。
文字列指定では内部的に 「PropertyToID」 を実行し、更にSetFloat
が実行されています。その他ID指定と比べると処理項目が多いことが分かります。
PropertyToIDで事前にキャッシュがオススメ
PropertyToIDのパフォーマンスが高いことが分かりました。では実際どのようにPropertyToIDを使用したらよいか解説していきます。
結論、事前キャッシュです。ゲーム起動時にキャッシュして使い回す方法がおすすめの方法です。なぜなら パラメーターのIDはゲーム実行中変更されないため です。
public class Test : MonoBehaviour
{
// シェーダーIDをキャッシュ
public static readonly int ColorId = Shader.PropertyToID("_Color");
}
上記のコードのようにゲーム起動時にIDを取得しておくとゲーム実行中に無駄な処理が走らずに済むためオススメです。
まとめ
本記事ではPropertyToIDを使ったシェーダーのパフォーマンスアップについて解説してきました。
シェーダーは複雑になればなるほど負荷が上がってきます。今回紹介したテクニックは小さな改善にはなりますが、パフォーマンスチューニングは小さい改善の積み重ねです。
PropertyToIDは知ってて損のない手法ですし、デメリットがないためぜひ積極的に使用してもらえればと思います。
PropetyToIDはVisual Effect GraphのイベントID取得にも使用されています。

筆者のXをフォローしよう