PixiJS のゲームがカクつくのはなぜ?
PixiJS は速いです。だからこそ、Pixi のゲームのカクつきはもどかしいのです。レンダラーは何万ものスプライトを描けるので、フレームが落ちたなら何か別のことが起きています。Myaku はそれが何かを突き止めます。
ゲームに追加する
npm install -D myaku<!-- index.html:ゲームのスクリプトより前に -->
<script type="module">import "myaku/auto";</script>
<script type="module" src="/src/main.ts"></script>これだけです。Myaku は Pixi 自身の devtools と同じフック(__PIXI_APP_INIT__)を使って PixiJS 8 にフックするので、Application が起動すると Myaku が自分で見つけます。何かを渡す必要も、ラップする必要もありません。
ticker か、レンダラーか
Pixi のフレームが遅いとき、まず知りたいのは、時間を使ったのがゲームロジックと描画のどちらなのかです。Myaku は 2 つのスパンでこれに答えます。
update:ticker のリスナー、つまりapp.ticker.add(…)で追加したコードすべてrender:Pixi のレンダラーがステージを描く処理
PixiJS 8 のゲームに 3 ms 忙しく働くだけの ticker リスナーを追加して確かめたところ、Myaku は update を 1 フレームあたり 3 ms、render を 0.2 ms と報告しました。
つまり、遅いフレームの判定はこう読めます。
Frame 4,410 took 31 ms (budget 25 ms). The game's frame code ran 29 ms. Spans: update 27 ms, render 1.6 ms.
(フレーム 4,410 に 31 ms かかりました(予算 25 ms)。ゲームのフレーム処理に 29 ms。スパン:update 27 ms、render 1.6 ms)
問題は Pixi ではなく、あなたのロジックです。どの部分かを知るには、自分のシステムを計測しましょう。
import { myaku } from "myaku";
const profiler = myaku();
app.ticker.add((ticker) => {
profiler.span("movement", () => moveEntities(ticker.deltaMS));
profiler.span("collisions", () => checkCollisions());
});PixiJS でよくある容疑者
upload:プレイ中の新しいテクスチャ。Texture.from(canvas)、毎フレーム文字が変わるTextオブジェクト、その場で作るRenderTextureが当てはまります。テクスチャがまだアップロードされていないスプライトの初回描画もそうです。Myaku はフレームごとのアップロード回数とバイト数を数えます。テクスチャは prepare プラグイン(import "pixi.js/prepare"してからrenderer.prepare.upload(…))で先にアップロードしましょう。頻繁に変わるテキストにはBitmapTextがおすすめです。gc:毎フレームのメモリ確保。 ticker の中で作る新しいPointやRectangle、表示リストに対するfilter/map、ホットループ内のgetBounds()(メモリを確保します)。オブジェクトを使い回しましょう。compile:フィルターの初回使用。 新しいフィルターやカスタムシェーダーは、初めて描かれるときにコンパイルされます。ローディング画面の裏で温めておきましょう。- 大量のドローコール。 フレームは遅いのにコードは速かった場合、ドローコールが多ければ Myaku の判定がそれに触れます。テクスチャを減らし(アトラス化)、ブレンドモードやフィルターの切り替えを減らせば、Pixi はもっとまとめてバッチできます。
throttled:ゲームのせいではありません。 隠れたウィンドウや最小化されたウィンドウはブラウザに間引かれます。Myaku はそう伝えます。
共有できる数字
window.__MYAKU__.report() はただの JSON です。p50、p95、p99 のフレーム時間、1 分あたりのヒッチ回数、判定付きのワーストのヒッチ、そして update、render、自分で追加したスパンの平均コストが入っています。