LoginSignup
13
10

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-04-17

マテリアルのシェーダを切り替えると未使用のプロパティがたまっていく。(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
13
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
10