Help us understand the problem. What is going on with this article?

Unityでマテリアルの未使用のプロパティを削除してサイズを減らす

More than 1 year has passed since last update.

マテリアルのシェーダを切り替えると未使用のプロパティがたまっていく。(Unity 2017.3.1p3で確認)
例えば次のようにしてマテリアルを作るとする。

  • Createのメニューからマテリアルを作成する(デフォルトでStandardシェーダがつく)
  • パーティクルで使うのでシェーダをParticle/Additiveに変更する

このときマテリアルのパーティクル用のシェーダにしてもStandardシェーダのプロパティが残ったままになる。

material_property_debug_ss.png

デバッグ表示すると Unlit/Color シェーダでも _BumpMap などのプロパティがついている。

未使用のプロパティを削除する

なので削除するエディタ拡張を書いた。マテリアルに割り当てられているシェーダのプロパティに存在しないプロパティは削除する。

[MenuItem("Assets/Delete Unused MaterialProperty")]
public static void DeleteUnusedMaterialProperty()
{
    var m = Selection.activeObject as Material;
    if (m == null)
    {
        return;
    }

    if (m.shader == null)
    {
        return;
    }

    HashSet<string> properties = new HashSet<string>();
    int count = ShaderUtil.GetPropertyCount(m.shader);
    for (int i = 0; i < count; i++)
    {
        string propName = ShaderUtil.GetPropertyName(m.shader, i);
        properties.Add(propName);
    }

    var so = new SerializedObject(m);
    var sp = so.FindProperty("m_SavedProperties");

    var texEnvSp = sp.FindPropertyRelative("m_TexEnvs");

    for (int i = texEnvSp.arraySize - 1; i >= 0; i--)
    {
        string propName = texEnvSp.GetArrayElementAtIndex(i).FindPropertyRelative("first").stringValue;

        if (!properties.Contains(propName))
        {
            texEnvSp.DeleteArrayElementAtIndex(i);
        }
    }

    var floatsSp = sp.FindPropertyRelative("m_Floats");

    for (int i = floatsSp.arraySize - 1; i >= 0; i--)
    {
        string propName = floatsSp.GetArrayElementAtIndex(i).FindPropertyRelative("first").stringValue;

        if (!properties.Contains(propName))
        {
            floatsSp.DeleteArrayElementAtIndex(i);
        }
    }

    var colorsSp = sp.FindPropertyRelative("m_Colors");

    for (int i = colorsSp.arraySize - 1; i >= 0; i--)
    {
        string propName = colorsSp.GetArrayElementAtIndex(i).FindPropertyRelative("first").stringValue;

        if (!properties.Contains(propName))
        {
            colorsSp.DeleteArrayElementAtIndex(i);
        }
    }

    so.ApplyModifiedProperties();
}

マテリアルのサイズ変化

  • 削除前のマテリアルのサイズ:2000 byte
  • 削除後のマテリアルのサイズ:715 byte

Androidでランタイムのサイズを Profiler.GetRuntimeMemorySizeLong で計測。ランタイムではプロパティを削除できないので2つマテリアルを用意して計測。

  • 削除前のマテリアルサイズ:1440 byte
  • 削除したマテリアルサイズ:984 byte
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away