はじめに
UnityのParticleSystemでは使用したい機能(モジュール)を追加をし、モジュールによってはMeshやTextureを設定して使用することができます。
しかし、一度モジュールにチェックをいれ、Meshを登録した後にモジュールのチェックを外すとMeshのアセット参照は残ったままになります。
そのためパーティクルをロードする際に不必要なアセットも巻き込んでロードされます。
これを防ぐために必要のないアセット参照は消すEditor拡張を作りました。
ソースコード
仕組み
スクリプトで全プロパティをチェックして不要であれば消す…といった方法をできればよかったのですができなかったので各モジュールやEnumを設定した場合にアセットを設定できそうであればそれをif文でチェックしてNullを代入して消すといった方法で消してます。
1つのアセット参照を消す場合
例えばShapeモジュールの場合です。
ShapeがConeの時はTextureだけを入れることができます。
しかし、ShapeをMeshに変更すると
Meshの登録ができるようになります。
private void ClearShapeModuleProperties(ParticleSystem particleSystem)
{
var shapeModule = particleSystem.shape;
// shapeModuleが使用されていなかったら関係するアセット参照を消す
if (!shapeModule.enabled)
{
shapeModule.texture = null;
shapeModule.mesh = null;
shapeModule.meshRenderer = null;
shapeModule.skinnedMeshRenderer = null;
shapeModule.sprite = null;
shapeModule.spriteRenderer = null;
return;
}
// 対応したMesh以外にアセット参照がある可能性があるので消す
switch (shapeModule.shapeType)
{
case ParticleSystemShapeType.Mesh:
shapeModule.meshRenderer = null;
shapeModule.skinnedMeshRenderer = null;
shapeModule.sprite = null;
shapeModule.spriteRenderer = null;
break;
// 他にもパターンがあるが説明のために省略
default:
// どれにも一致しない場合はすべて除去
shapeModule.mesh = null;
shapeModule.meshRenderer = null;
shapeModule.skinnedMeshRenderer = null;
shapeModule.sprite = null;
shapeModule.spriteRenderer = null;
break;
}
}
そのためこのようなコードを作成します。
まず、そもそもShapeモジュールを使用しないときはif (!shapeModule.enabled)
の中ですべてのアセット参照にNullを入れます。
どんなアセット参照がこのモジュールにあるのかはモジュールのすべてのチェックマークやEnumをポチポチ切り替えて探します。
Shapeに設定されているモードがMeshの場合はcase ParticleSystemShapeType.Mesh:
でMesh以外のアセット参照を消します。
Coneなどを設定されている場合はMeshすらいらないのでdefault:
でMeshも含めて全部消します。
Listを消す場合
CollisionモジュールなどではListを持っています。
この場合もモジュールを使わない場合やTypeがPlanesではない場合は参照を持つ必要がないので消します。
// 全てのPlaneを消す
void RemoveAllPlane()
{
var planeCount = collisionModule.planeCount;
if (planeCount > 0)
{
for (int i = planeCount - 1; i >= 0; i--)
{
collisionModule.RemovePlane(i);
}
}
}
このようなメソッドを作り、for文では要素を後ろから消します。
後ろから消している理由は普通に消すとRemovePlane
ではそのIndexのPlaneが消え、以降のPlaneが詰められるせいで全部消せなかったりしたため後ろから消します。
また、
void ClearAllPlanes()
{
for (int i = 0; i < 6; i++)
{
collisionModule.SetPlane(i, null);
}
}
をこのようにNullを直接代入した場合はすべてNullになるため参照は消えますがListの大きさが確保されたままになってしまったのでやめまs