roblox-performance について
Roblox 開発者向けのパフォーマンス分析・最適化スキルです。サーバー、クライアント、メモリ、ネットワーク、ロードのどこがボトルネックかを特定し、適切なツールと対策を選ぶ方法を扱います。
主な機能
- 01Roblox のパフォーマンス分析ツールの利用
- 02メモリリークと計算のボトルネックの特定
- 03Luau のホットパスと描画アセットの最適化
- 04物理、ネットワーク、ロード負荷の削減
- 05Parallel Luau による計算の分散
活用シーン
- 01クライアントのフレームレート低下やサーバー遅延の調査
- 02増え続けるメモリ使用量の分析
- 03遅延やネットワーク同期問題の軽減
- 04ゲーム参加とアセット読み込み時間の短縮
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ el4cteo/ roblox-skills --skill roblox-performanceインストール後、Claude Code で/roblox-performanceを入力して読み込まれたか確認します。
同梱ファイルreferences/profiling.md
詳細
Roblox のパフォーマンス
最適化の前に計測しましょう。 ボトルネックがサーバーの処理、クライアントの処理(CPU/GPU)、メモリ、ネットワーク、読み込み時間のどれにあるかを特定し、それに合ったツールを使います。
ツール
| ツール | 開き方 | 用途 |
|---|---|---|
| Developer Console | F9(ゲーム内) | エラー、カテゴリ別のサーバー/クライアントメモリ、ネットワーク、スクリプトの動作を確認できます。ライブサーバーで動作します。 |
| MicroProfiler | Ctrl+Alt+F6(⌘⌥F6);サーバーは Dev Console | フレームごとの処理時間やスパイクを確認し、詳細を調べるためにフレームをダンプできます。 |
| Script Profiler | Studio / Dev Console | どの関数が Luau の処理時間を消費しているかをサンプリングして確認できます。 |
| Luau heap snapshots | Dev Console → Memory → Luau Heap | どのテーブル、クロージャ、インスタンスが何によって保持されているか(リーク)を確認できます。 |
| Scene Analysis | Studio | スクリプトメモリ、親のないインスタンス(リーク)、インスタンス構成、オーディオ/アニメーションのメモリ、三角形数を確認できます。また、Studio MCP 経由で SceneAnalysisService を利用できます。 |
| Performance Stats / Debug Stats | Ctrl+Alt+F7 / Shift+Ctrl+F1–F5 | CPU/GPU/メモリ/ネットワークのリアルタイムオーバーレイを表示します。 |
| Network Simulator | Studio Device Simulator ツールバー | 遅延、ジッター、パケット損失がある環境(3G/4G/Wi-Fi プロファイル)でテストできます。 |
| Performance dashboard | Creator Hub | デバイス別の FPS、サーバーのハートビート、メモリ、クラッシュ率のライブ集計を確認できます。 |
MicroProfiler とメモリビューで、自分のコードにラベルを付けます。
--!strict
local RunService = game:GetService("RunService")
debug.setmemorycategory("EnemyAI") -- memory allocated by this thread is attributed to "EnemyAI"
RunService.Heartbeat:Connect(function(_deltaTime)
debug.profilebegin("EnemyAI.think") -- shows as a labeled bar in the MicroProfiler
-- ... work ...
debug.profileend()
end)
目標
- クライアント:ミッドレンジのスマートフォンで 60 FPS(約 16.6 ms/フレーム)。多くのプレイヤーはローエンドの Android デバイスを使用しています。
- サーバー:ハートビートを 60 Hz 近くに保ちます。
Stats(workspace:GetRealPhysicsFPS()、Dev Console Server Stats)で確認します。 - メモリ:モバイルクライアントは、まずメモリ不足(OOM)でクラッシュします。ローエンドデバイスではクライアントメモリを約 1~1.5 GB より十分低く保ち、
PlaceMemory、LuaHeap、GraphicsTexture、Sounds、Animationの各カテゴリを監視します。 - サーバーの OOM:メモリが通常の水準を超えると
game.ServerLowMemoryWarningが発火します(サーバーのみ。ライブサーバーと Team Test が対象で、Studio のプレイテストは対象外です)。その後もメモリが高い状態の間は 60 秒ごとに発火します。これを使ってメモリをすばやく解放し(デブリやエフェクトを破棄し、スポーンを一時停止し、誰もいないマップエリアをアンロードします)、ログを記録します。このイベント自体がメモリを解放することはありません。
--!strict
game.ServerLowMemoryWarning:Connect(function()
warn("Server memory high: cleaning up")
-- e.g. destroy temporary effects, pause NPC/item spawners until memory recovers
end)
よくある問題 → 対策
| 症状 | よくある原因 | 対策 |
|---|---|---|
| メモリが時間とともに増加する | 接続のリーク、プレイヤーやインスタンスをキーにしたテーブル、破棄後も参照されているインスタンス、親のないインスタンス | プレイヤーごと/キャラクターごとに接続を切断してクリーンアップします。PlayerRemoving でテーブルをクリアし、Scene Analysis の「unparented instances」とヒープスナップショットを使います。 |
| プレイヤーが多いとサーバーが遅くなる | プレイヤーごとのフレーム単位のループ、while true do task.wait() end ループ、負荷の高いリモートイベントハンドラー、固定されていない多数のパーツの物理演算 | イベント駆動型のコード、単一のスケジューラーループ、処理頻度の抑制を採用します。静的パーツを固定し、サーバーが所有するアセンブリを減らします。 |
| クライアントの FPS が低下する | パーツや描画呼び出しが多すぎる、多数のライトによる影、透明オブジェクトやパーティクルのオーバードロー、フレームごとの UI 更新 | メッシュを統合/インスタンス化し、小さなパーツでは CastShadow = false に設定します。影付きライトやパーティクルを減らし、変更時のみ UI を更新します。 |
| N 秒ごとにスパイクが発生する | 自動保存/GC の集中処理、プレイヤー間で同期したループ、大きな Clone() | ランダムなオフセットを使ってタイミングをずらし、オブジェクトをプールし、フレーム間で処理を分散します。 |
| ping が高い/ラバーバンド現象が起きる | リモートイベントの過剰送信、大きなペイロード、多数のプロパティ変更の複製 | バッチ処理、差分圧縮、送信頻度の抑制を行います。クライアント上でトゥイーンを使い、roblox-networking を参照します。 |
| 参加に時間がかかる | place が大きい、固有アセットが多い、ストリーミングがない | ストリーミングを使い、SLIM LOD を設定し、固有のメッシュ/テクスチャを減らします。ContentProvider:PreloadAsync は重要なアセットのみに使います。 |
Luau のホットパス
- サービス、インスタンス、
RaycastParamsはループの外でキャッシュし、フレームごとの処理でFindFirstChild/GetDescendantsを呼び出さないでください。GetDescendantsによる走査は、タグ(CollectionService)または維持管理されたセットに置き換えてください。 - フレームごとの処理には、
task.wait()のループではなく、Heartbeat/PreSimulationのdeltaTimeを使用してください。 - ホットループ内でフレームごとにクロージャーやテーブルを作成しないでください。
table.clearを使ってバッファーを再利用してください。 - 数値計算の多いコードでは、スクリプト全体に
--!native、または関数ごとに@nativeを使用してください。型付きパラメーターはネイティブコンパイラーに役立ちます。無条件に有効化しないでください。コンパイル時間がかかり、ネイティブコード用メモリーには全体の上限があります。 - Roblox はライブゲームをすでに
--!optimize 2でコンパイルしています。マイクロベンチマークで Studio の計測時間をあてにしないでください。
レンダリングとアセット
- パーツは数を減らして大きくしてください。
MeshIdを共有するMeshPartはインスタンス化されるため低コストです。ユニオン(PartOperation)は高コストになる場合があるため、Scene Analysis で三角形数を確認してください。 - 詳細なメッシュには
RenderFidelity = Automatic/Performanceを、装飾用メッシュにはCollisionFidelity = Box/Hullを使用してください。装飾専用の場合はCanCollide/CanQuery/CanTouch = falseにしてください。 - ライト:影を落とす
PointLight/SpotLight/SurfaceLightの数を制限してください。ParticleEmitter.Rateとパーティクルのサイズ(オーバードロー)、Beam/Trailの数も制限してください。 - テクスチャ/画像は再利用し、解像度を適切に保ってください(ほとんどの場合、最大 1024²)。
SurfaceAppearanceは控えめに使用してください。 - ストリーミング(
roblox-architecture)を有効にし、静的モデルにはModel.LevelOfDetail = SLIMを設定して、StreamOutBehavior = Opportunisticでメモリーを解放してください。
物理
- 動かす必要のないものはすべてアンカーしてください。移動するアセンブリに溶接された装飾パーツは、コストを増加させます。
- 衝突判定を減らしてシンプルにしてください(
CollisionFidelity、衝突グループを使ってペアをスキップ)。Touchedが不要な場合はCanTouch = falseにしてください。 - アンカーされていないパーツの
CFrameをフレームごとに設定しないでください。制約を使うか、アンカーしてからCFrameを設定してください。 - 多数のアンカー済みパーツを移動するには、
workspace:BulkMoveTo(parts, cframes, Enum.BulkMoveMode.FireCFrameChanged)を使用してください。 - 適応型タイムステップ(
PhysicsSteppingMethod = Adaptive)を使うと、物理演算の CPU 負荷を軽減できます。
Parallel Luau
異なる Actor インスタンスの下にあるスクリプトは並列実行できます。
--!strict
-- Script parented under an Actor (one Actor per logical unit, e.g. per NPC group or chunk).
local RunService = game:GetService("RunService")
local results: { number } = {}
RunService.Heartbeat:ConnectParallel(function(_deltaTime)
-- Parallel phase: read-only access to most instances, pure computation, thread-safe APIs (raycasts).
for i = 1, 100 do
results[i] = math.noise(i / 10, os.clock())
end
task.synchronize()
-- Serial phase: write to instances, fire events, call thread-unsafe APIs.
end)
task.desynchronize()/task.synchronize()でフェーズを切り替えます。ConnectParallelは並列実行で開始します。- 同じ Actor 内のスクリプトは相互に直列実行されるため、多数の Actor に処理を分散してください。
- デシンクロナイズ中は、ほとんどのインスタンスを
requireしたり変更したりできません。Actor:SendMessage/BindToMessageParallelまたはSharedTable(SharedTableRegistry)を使って通信してください。 - 適している処理:レイキャストの検証、プロシージャル生成、パスファインディング関連の数値計算、大規模シミュレーション。不向きな処理:小さなタスク(同期のオーバーヘッドが発生)、インスタンスを多用する処理。
プロファイリングの手順とメモリーリークの調査については、references/profiling.md を参照してください。
関連スキル
roblox-architecture(ストリーミング)、roblox-networking(帯域幅)、roblox-physics、roblox-npc-ai、roblox-studio-mcp(MCP を介した Roblox の rbx-perf-profiling/シーン分析)。
コメント
Markdown 対応