AssetBundleからモデルを使用するとメモリリークする問題と対策

[最終更新日 : 2017/12/19]

現在配布しているSDKにそのままインポートしたモデルをAssetBundle化した後、
作成したAssetBundleからモデルをロード・アンロードを行うとメモリリークが発生することがあります。

ここでは、その原因と未対応の理由、及びその対策について説明します。

 

概要

Live2Dモデルでクリッピングが設定されたモデルをAssetBundle化した後、そこからモデルをロード・アンロードを行うとメモリリークが発生します。
原因としてはRenderTextureがコピーされた後、生成されたまま削除されずに残ってしまうため、メモリリークが発生します。
対策はCubismMaskTextureの使用方法によって2通りあります。
注意点として、同時に2つの対策を同じプロジェクトで行わないでください。2つの対策は独立しています。

case 1: 一つのCubismMaskTextureを使用している場合
1-1, CubismMaskControllerInspector.csのEditorGUILayout.ObjectFieldを削除します
1-2, CubismMaskController.csでシリアライズされている_maskTextureをシリアライズをしない処理に変更します
1-3, AssetBundleを作り直します

case 2: モデルごとにCubismMaskTextureをインスタンスしている場合
2-1, CubismMasktexture.csに、_renderTextureを削除するメソッドを作成します
2-2, モデルを破棄するタイミングで2-1で作成したメソッドを呼び出します
2-3, AssetBundleを作り直します

上記の対策どちらかを行うことでメモリリークは解消されます。

 

背景・原因

Live2Dモデルでクリッピングが設定されたモデルをAssetBundle化した後、そこからモデルをロード・アンロードを行うとメモリリークが発生します。

原因としては、モデルをロードするたびにマスク用のRenderTextureが生成され、モデルが削除されてもRenderTextureは残ってしまうためです。
コンポーネントに設定されているオブジェクトは、オブジェクトの参照ではなくオブジェクトのコピーでAssetBundle化されます。
その結果、AssetBundle化を通してモデルを生成するとCubismMaskController.MaskTextureにCubismMaskTextureのインスタンスであるGlobalMaskTextureがセットされている場合、モデルをロードするたび同時にGlobalMaskTextureのコピーも生成され、RenderTextureも作られます。
しかしモデルを削除してもRenderTextureは削除されずに残ってしまいます。その結果、メモリリークが発生します。

Cubism SDKへの、本不具合の修正反映は、以下の3つの理由によって行っておりません。

  1. マスク用RenderTextureの扱い方によって対応方法が異なるため
  2. わかりやすさ、構造のシンプルさに重点を置いているCubismComponentsが複雑化してしまうため
  3. AssetBundleを利用しない場合は問題がないため

 

対策

対策における注意点

本項では2つの対策を提示しています。
しかし2つの対策は独立した対策方法のため、同時に2つの対策を1つのプロジェクトで行わないでください。

対策はCubismMaskTextureの使い方によって対策が異なります。一つのCubismMaskTextureだけを使用している場合と、モデルごとにCubismMaskTextureをインスタンスして使用している場合です。
ここでは2つの使用方法に対して、それぞれ1つずつ対策の説明を行います。

Case 1: 一つのCubismMaskTextureを用いてモデルを表示する場合

一つのCubismMaskTextureを使いまわして、モデルを表示している場合はこちらの対策を行います。

まず最初に、CubismMaskControllerInspector.cs内に含まれているEditorGUILayout.ObjectFieldを削除します。

 

次にCubismMaskController.csでシリアライズされている_maskTextureをシリアライズしない処理に変更します。

 

これで対策ができました。
この後、AssetBundleを作り直してください。

case 2: モデルごとにCubismMaskTextureをインスタンスしている場合

モデルごとにCubismMaskTextureをインスタンスしている場合の対策はこちらになります。

最初にCubismMaskTexture.csに_randerTextureをDestroyするpublicメソッドを作成します。
以下はコード例です。

 

先述したメソッドをモデルを破棄するタイミングで呼び出します。
結果、モデルと同様にRenderTextureを削除することができます。

以上の対策が終わった後、AssetBundleを作り直してください。

 

Copyright © 2018 Live2D Inc.