Rendererモジュールの基本を抑え、Z-ファイティングや基本的な負荷計算を学んだ後に待っているのは、【エディタでは動くのに、実機でだけ挙動がおかしい・あるいは落ちる】 という実務上の地雷原です。
今回は、前回の記事で触れなかった【”GPU過負荷によるアプリの死” のメカニズムと、エフェクト制作における”理不尽なバグへの対処法”】をまとめました。
「FPS低下」の先にある絶望:GPU過負荷がクラッシュを招く理由
多くのアーティストは「負荷が高い=カクつく」と考えがちですが、モバイル開発においては【負荷が高い=OSによって強制終了される】という結末が待っています。
特にiOSにおける「死のメカニズム」を理解しましょう。
1. メモリの「 Jetsam(ジェトサム)」:VRAM枯渇の末路
スマホはPCと異なり、CPUとGPUで同じメモリを共有する「ユニファイドメモリ」構造です。
-
犯人はテクスチャとレンダーターゲット: エフェクトで巨大な非圧縮テクスチャを多用したり、ディストーション(GrabPass)を重ねたりすると、VRAM使用量が急増します。
-
OSによる粛清: iOSには「Jetsam」というメモリ監視機構があります。OS側が「このアプリはメモリを使いすぎでシステム全体を不安定にしている」と判断した瞬間、警告もログも残さず、アプリのプロセスを即座にキルします。
これが、開発者を悩ませる「何もしてないのにアプリが落ちた(OOMクラッシュ)」の正体です。
2. TDR(Timeout Detection and Recovery):GPUの「沈黙」
GPUは命令を受け取ると計算を始めますが、あまりにも複雑なシェーダーや重なりすぎたパーティクルを処理しようとすると、1フレームの計算に数秒かかることがあります。
-
OSの忍耐の限界: OSは数秒(多くは2秒程度)GPUが応答しないと、「GPUがフリーズした」とみなしてドライバをリセットします。
-
結果: アプリは即座にクラッシュします。これはFPSが1まで落ちた瞬間に発生しやすいため、爆発エフェクトの「重なり」が引き金になります。
3. サーマルスロットリング:熱による性能低下の悪循環
高負荷なエフェクトを出し続けると、デバイスが発熱します。
-
デバイスが熱くなる。
-
OSがハード保護のため、GPUのクロック周波数を下げる。
-
描画能力が落ちるため、さらにFPSが下がり、計算が滞る。
-
前述のTDR(タイムアウト)が発生しやすくなり、最終的にクラッシュする。
【教訓】 エフェクトの最適化は、単に「滑らかに動かすため」ではなく、【ゲームを継続させる(落とさない)ため】 の必須工程なのです。
エフェクトアーティストを襲う「三大あるあるバグ」とその回避策
Z-ファイティング以外にも、現場で悲鳴が上がる定番のバグがあります。
これらは「設定一つ」で解決できることが多いですが、原理を知らないと一生解決できません。
1. 【消失バグ】画面端に行くとパッと消える(Culling Boundsの罠)
画面の中央にエフェクトがあるときは正常なのに、画面の端に寄せた瞬間にエフェクトが消失する現象です。
-
原因: Unityは負荷軽減のため、カメラの視錐台(Frustum)の外にあるオブジェクトを描画しません。
この判定は、エフェクトの「バウンディングボックス(境界線)」で行われます。
パーティクルが激しく動いて発生源から遠くへ飛んでも、この「箱」が自動で広がらない設定になっていると、Unityは「本体は画面外だから、中身も全部消していい」と判断してしまいます。 -
回避策: Particle Systemの
Rendererモジュールにある “Culling Mode” を確認してください。-
Pause: 画面外で計算を止める(基本)。
-
Always Simulate: 画面外でも計算し続ける(重いが、消えるのは防げる)。
-
中級者の解:
Pauseにしつつ、Meshなどの境界線をCustom Simulation Spaceで手動で広げ、描画判定を担保する。
-
2. 【歪みバグ】親をスケールさせると形が崩れる(Scaling Modeの呪い)
「キャラクターの演出用に、エフェクトを縦に引き伸ばしたら、中の火花まで楕円形になった」という問題です。
-
原因: UnityのTransformは親のScaleを子に継承させますが、パーティクルの物理計算はこの「非均等な歪み」を正しく扱えません。
-
回避策: Mainモジュールの “Scaling Mode” を切り替えます。
-
Hierarchy: 親の歪みをそのまま受ける(デフォルト・バグの元)。
-
Local: 親のスケールを無視し、自分自身のスケールだけを参照する。
-
Shape: 親のスケールに従って「発生範囲」だけを広げ、個々のパーティクルの「形」は保つ。 実務では、ほとんどのケースで
ShapeかLocalに設定するのが安全です。
-
3. 【同期バグ】ポーズ中なのにエフェクトだけ動く
「メニューを開いて時間を止めたのに、後ろでエフェクトだけが元気に動いている」現象です。
-
原因: Unityの
Time.timeScaleに依存しているかどうかの違いです。 -
回避策: Mainモジュールの “Delta Time” 設定を使い分けます。
-
Scaled: ゲーム内時間に同期(ポーズで止まる)。通常の爆発など。
-
Unscaled: 実時間に同期(ポーズ中も動く)。UI演出や、スロー演出中の特定エフェクト。
-
アセット制作における「プロの作法」:テクスチャとメッシュ
前回の「Alpha Clipはモバイルで重くなる」という議論をベースに、アセット段階でできる回避策をまとめます。
1. テクスチャの「ジャリジャリ」を防ぐ(Mipmaps & Moiré)
カメラを引いた時に、エフェクトに不自然な砂嵐状のノイズが出る現象です。
-
対策: インポート設定の “Generate Mip Maps” は必ずオンに。遠くのピクセルを適切にボカしてくれるため、Z-ファイティングに近い視覚的ノイズを抑えられます。
2. Mesh Trimming(メッシュ・トリミング)の徹底
「半透明シェーダーにAlpha Clip(discard)を入れるとTBDRアーキテクチャでは重くなる」問題の、物理的な解決策です。
-
手法: 四角い板ポリゴンを使うのではなく、テクスチャの「透明な空白部分」を削るように、ポリゴンを16角形程度に割ってメッシュ化します。
-
なぜこれが正解か: スマホGPUにとって、「頂点数が増えるコスト」よりも「透明なピクセルを重ねて描画する(オーバードロー)コスト」の方が遥かに高いからです。中抜きのある「〇」や「三日月」のようなエフェクトは、メッシュ化するだけで劇的に軽くなります。
総括:エンジニアに「重い・バグってる」と言わせないために
エフェクトアーティストの真の価値は、美しい絵を作るだけでなく、【その絵がゲームの中で安全に動き続けること】 を保証できる知識にあります。
-
クラッシュ対策: テクスチャを圧縮(ASTC 6×6〜8×8)し、VRAMを Jetsam の手から守る。
-
歪み対策: 親オブジェクトのScaleを弄る際は、Scaling Modeを
Shapeにする習慣をつける。 -
カリング対策: 激しく動くエフェクトは、バウンディングボックスのサイズを事前に最大値で固定(Custom Bounds)しておく。
