このページでは、コモンなパフォーマンス問題とそれらを軽減するためのベストプラクティスについて説明します。
スクリプト計算
Lua コードの高価なオペレーションは、処理するのに長くかかり、それによりフレームレートに影響を与える可能性があります。並行して実行されていない場合、Lua コードは同期され、スレッドを生成するまで主スレッドをブロックします。
一般的な問題
テーブル構造に対する専門的な操作 - 複雑なオペレーション、例えばシリアル化、デシリアル化、および深度クローンは、特に大きなテーブル構造において高いパフォーマンスコストがかかります。これは、これらのオペレーションが再帰的であるか、または非常に大きなデータ構造を意味する場合に特にそうです。
高周波イベント - 周波数の高いオペレーションをフレームベースのイベントの RunService に結び付けることなく、フレームごとにオペレーションを繰り返すことで、計算時間が不要になることがあります。これらのイベントには、次の内容が含まれます:
ミトレーション
- Class.RunService イベントでコードを呼び出すたびに、高い周波数の呼び出しが必要な場合にのみ使用を制限し、他のコードを他のイベントで実行するか、<code> ループ</code> で実行することができます。
- 大きなまたは高価なタスクを task.wait() を使用して、ワークを複数のフレームに分割します。
- 必要ない高コストのオペレーションを識別し、多スレッド を使用して、データモデルにアクセスする必要のない計算コストの高いタスクを優先します。
- 一部のサーバー側スクリプトは、ネイティブコード生成 から利益を得ることができます。これは、スクリプトをマシンコードでコンパイルし、バイトコードではなくて機械コードでコンパイルするプレーグを使用することで、簡単なフラグです。
MicroProfiler スコープ
スコープ | 関連する計算 |
RunService.PreRender | プレレンダーイベントで実行されているコード |
RunService.PreSimulation | ステップイベントで実行されているコード |
RunService.PostSimulation | 心音イベントで実行されているコード |
RunService.Heartbeat | 心音イベントで実行されているコード |
For more information on debugging scripts using the MicroProfiler, see the debug library, which includes functions for tagging specific code and further increasing specificity, such as debug.profilebegin and debug.profileend . Many Roblox API methods called by scripts also have their own associates MicroProfiler tags that can provide useful signal.
スクリプトメモリ使用
メモリリークは、ガビジンコレクターが使用できなくなったときにスクリプトを書き込むとメモリが消費されるために発生します。リークは、特にサーバーで発生します、メモリが使用され続けることができます。クライアントセッションは、多くの日数、メモリが使用されているためにオンラインになることができますが、メモリリークは、メモリが使用されていないためにオ
次のメモリ値は、 開発者コンソール で問題を示す可能性があります:
- LuaHeap - 高いまたは減少する使用量はメモリ漏れを示唆します。
- InstanceCount - インスタンスの数を一貫して増やすと、コードのいくつかのインスタンスに対する参照が見つかりません。
- PlaceScriptMemory - メモリの使用量のスクリプトを提供します。
一般的な問題
接続を切断して接続された接続を完了する - エンジンは、接続されたインスタンスと任意の値に接続されたイベントを収集したことがありません。ただし、接続されたインスタンス内のエンコードされたイベントとコードは、メモリガービジョンコレクターには無効です。たとえイベントが発動している場合でも。
インスタンスが所有するインスタンスが破壊されると、イベントは関連する Player オブジェクトを破壊します。ユーザーがエクスペリエンスを終
テーブル - テーブルにオブジェクトを挿入するが、それらが不要になったときに削除しないことで、メモリが不要になります。特に、ユーザーのデータを追跡するテーブルの場合、次のコードサンプルは、ユーザーが参加するたびにユーザー情報を追加するためのテーブルを作成します:
例local playerInfo = {}Players.PlayerAdded:Connect(function(player)playerInfo[player] = {} -- いくつかの情報end)必要なくなったときにこれらのエントリを削除しないと、テーブルはサイズが拡大し、ユーザーがセッションに参加するにつれてメモリが消費されるようになります。これらのコードは、テーブルがサイズが拡大するにつれて、よりコンピューターに費用がかかるようになります。
ミトレーション
メモリー漏れを防ぐために使用されるすべての値をクリアするには:
すべての接続を切断する - コードベースを通じて、各接続を以下のパスの 1 つで確認してください:
- Disconnect() 関数を使用して手動で切断します。
- イベントが所属するインスタンスを Destroy() 関数で破壊します。
- 接続先のスクリプトオブジェクトを破壊する。
プレイヤーオブジェクトとキャラクターを削除してから戻る - ユーザーが去ると、コードを実装して、次の例のように、接続がユーザーの後に残りないようにする:
例Players.PlayerAdded:Connect(function(player)player.CharacterRemoving:Connect(function(character)task.defer(character.Destroy, character)end)end)Players.PlayerRemoving:Connect(function(player)task.defer(player.Destroy, player)end)
物理学計算
過度な物理シミュレーションは、サーバーとクライアントの両方のフレームごとの計算時間の増加につながる可能性があります。
一般的な問題
- 過度な物理時間ステップフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィーチャーフィー
精度の向上した物理の固定モードも利用可能で、これにより、すべての物理アセンブルが 240 Hz (フレームごとに 4 回) でステップします。これにより、各フレームごとに大幅に増加する計算が発生します。
シミュレートされたオブジェクトの複雑さの過剰な増加 - シミュレートされたオブジェクトの複雑さが多すぎると、フレームごとにより長くなります。オフィスエクスペリエンスは、必要なメカニズムやジョイントがないオブジェクトをシミュレートしている場合があります。
過度に精密な衝突検知機能付きメッシュパーツ - メッシュパーツには、CollisionFidelity プロパティがあり、さまざまなパフォーマンスレベルでの衝突を検知するための多くのモードを提供します。精密なメッシュパーツの衝突検知モードは、最高の
ミトレーション
シミュレーションが必要ないパーツに固定する - 静的 NPC の場合など、シミュレーションが必要ないパーツをすべて固定します。
適応的な物理を使用する - 適応的なステップは、物理メカニズムの物理計算の速度を動的に調整し、物理メカニズムの場合、物理更新を少なくすることができます。
メカニズムの複雑さを減少する * できるだけ、アセンブリ内の物理コンストリンクまたはジョイントの数を最小限に抑えます。
- 自己衝突を減少するために、ラグドールのリミットや非衝突の制限を適用したり、限定を適用したりして、ラグドールのリミットを設定して、それらが互いに衝突しないようにします。
精密な衝突の忠実度の使用を減少する * ユーザーが違いを気づくことのない小さなオブジェクトや非インタラクティブオブジェクトの場合は、ボックスの忠実度を使用してください。
小さいサイズのオブジェクトには、ボックスまたは船体のフィデルティティを使用して、形状に応じて適切にサイズを変更できます。
大きく複雑なオブジェクトの場合、可能であれば透明なパーツを使用してカスタムコリジョンを構築してください。
当たり判定が必要ないオブジェクトの場合、当たり判定を無効にし、ボックスまたは船体の忠実度を使用することで、当たり判定のゲーム内の再利用が可能になります。
Studio では、コリジョンフィデルティ をオプションの ビジュアライズ ウィジェットから切り替えることで、コリジョンのゲージをデバッグ用にレンダリングできます。
あるいは、CollisionFidelity = Precise フィルターを Explorer に適用し、精密なフィデルティでメッシュパーツのカウントを表示し、簡単に選択できます。
For an in-depth walkthrough on how to choose a collision fidelity option that balances your precision and performance requirements, see 物理とレンダリングパラメーターを設定する .
MicroProfiler スコープ
スコープ | 関連する計算 |
物理学Stepped | 全体的な物理コンピュート |
ワールドステップ | 毎フレームで実行される不連続な物理ステップ |
物理メモリ使用
物理の移動と衝突検知はメモリを消費します。メッシュパーツには CollisionFidelity プロパティがあり、メッシュの衝突限界の評価に使用されるアプローチを決定します。
一般的な問題
デフォルトと精密な衝突検知モードは、低精度の衝突形状の 2つの他のモードよりもメモリを大幅に消費します。
PhysicsParts の下でメモリ使用量が高すぎると、エクスペリエンスでオブジェクトの 衝突フィデルティ を減少する必要があります。
軽減方法
衝突の忠実度に使用されるメモリを減少するには:
- 当該しないパーツの場合は、BasePart.CanCollide 、BasePart.CanTouch および BasePart.CanQuery を設定して、2>Class.BasePart.CanRender2> を無効にします。
ヒューマノイド
Humanoid はプレイヤーと非プレイヤーキャラクター(NPC)のための機能の幅広い範囲を提供するクラスです (NPC)。パワフルですが、Humanoid はコンピュートコストが大きいことがあります。
一般的な問題
- NPC に人形状態タイプをすべてオンにすると、パフォーマンスコストがかかります。 - 特定の HumanoidStateTypes に必要なコストがあります。無要な状態を無効にするためには、Climbing 状態を無効にす
- 人形と一緒にモデルをインスタンス、変更、およびリスポーンするたびに * これはエンジンが処理するのに苦労する可能性があります、特にこれらのモデルが レイヤード衣装 を使用している場合。これはまた、アバターが頻繁にリスポーンするエクスペリエンスで特に問題があります。
- In the MicroProfiler , lengthy updateInvalidatedFastClusters tags (over 4 ms) are often a signal that avatar instantiation/modification is triggering excessive invalidations.
- 人間形を使用するが、それらが必要でない場合 - 通常動く Static NPC は、Humanoid クラスを必要としません。
- サーバーから大量の NPC にアニメーションをプレイする際には、NPC アニメーションはサーバーでシミュレートしてクライアントにレプリケートする必要があります。これはサーバー上の不要なオーバーヘッドになる可能性があります。
ミトレーション
- クライアント上の NPC アニメーションをプレイする - 大規模な NPC のエクスペリエンスでは、クライアントに Animator を作成し、アニメーションをローカルで実行することを検討してください。これにより、サーバーの負荷が軽減され、必
- ヒューマノイドに使用しやすい代替を使用する - NPC モデルは必ずしもヒューマノイドオブジェクトを含む必要はありません。
- 静的 NPC の場合、単純な AnimationController を使用してください、移動する必要はありませんが、アニメーションをプレイするだけです。
- NPC を移動する場合は、自分の移動コントローラーを実装し、NPC の複雑さに応じて AnimationController を使用することを検討してください。
- 使用されていないヒューマノイドの状態を無効にする - 必要な状態のみを有効にするには、Humanoid:SetStateEnabled() を使用します。
- NPC モデルを頻繁にリスポーンするPool NPCモデル - 代わりに NPC をプールに再送信します。これにより、NPC が再スポーンするたびに、プールの NPC の 1つを再起動できます。このプロセスは、プロセスの最小限に抑えられるように、NPC がプールに再送信するたびに再起動
- 近くにいるユーザーの近くにNPCをのみ出現させる - ユーザーが範囲外にいるとNPCを出現させない - ユーザーが範囲を離れると、NPCをクリアする。
- アバターのインスタンス後にアバターの階層に変更を加えないでください - アバターの階層に対するいくつかの変更は、パフォーマンスの重大な影響を持つ可能性があります。一部の最適化は利用可能です:
- カスタムプロシージャルアニメーションの場合、JointInstance.C0 および JointInstance.C1 プロパティを更新しないでください。代わりに、Motor6D.Transform プロパティを更新します。
- アバターに BasePart オブジェクトを追加する必要がある場合は、アバターの Model 階層の外で行ってください。
MicroProfiler スコープ
スコープ | 関連する計算 |
ステップヒューマノイド | ヒューマノイドのコントロールと物理 |
ステップアニメーション | ヒューマノイドとアニメーターアニメーション |
更新されたFastClusters | アバターをインスタンスするか、変更するために関連付けられています |
レンダリング
クライアントが各フレームを通過するときの主要な部分は、現在のフレームでシーンをレンダリングすることです。サーバーはレンダリングを行わないので、このセクションはクライアント専用です。
ドローコール
ドローコールは、エンジンからGPUに何かをレンダリングするための指示セットです。ドローコールには、オーバーヘッドが大きい。一般的に、フレームごとにかかるコンピューティング時間が少なくなるにつれて、ドローコールの使用は減少します。
現在、 Render Stats > Timing アイテムで Studio で何個のドローコールが発生しているかを見ることができます。クライアントで Render Stats を表示するには、1>Shift1> を押すか、3>F23> を押すことでクライアントで 6>Render Stats6> を表示できます。
あなたのシーンで指定されたフレーム内のオブジェクトが描かれる必要があるほど、GPUに対するドローコールは増えます。ただし、Roblox エンジンは、「instancing」というプロセスを使用して、同じテクスチャのメッシュを単一のドローコールでコラプします。特に、「 MeshId
- 素材は、SurfaceAppearance と MeshPart.TextureID が存在しないときに同じです。
他の一般的な問題
過度なオブジェクトの密度 - 大量のオブジェクトが高密度で集中する場合、このシーンのこのエリアのレンダリングには、より多くのドローコールが必要になります。マップの特定の部分を見ていると、フレームレートが低下する可能性があります。
デカール、テクスチャ、パーティクルなどのオブジェクトは、バッチ処理されずに追加のドローコールを介紹します。これらのオブジェクトタイプをシーンで注意深く見る必要があります。特に、ParticleEmitters のプロパティ変更は、パフォーマンスに大きな影響を与える可能性がありま履行。
インスタンス機会を逃しました - 場面には、複数の回、同じメッシュが複製されている場合がありますが、メッシュのコピーには異なるメッシュまたはテクスチャアセット ID があります。これはインスタンスを避けることができ、不要なドローコールを引き起こす可能性があります。
この問題のコモンな原因は、Roblox にインポートされた個々のアセットではなく、全体のシーンをインポートしたときに、ポストインポートをアセンブルするためにRoblox にダブルデュプレートされることです。
過度なオブジェクトの複雑さ - ドローコールの数と同じくらい重要ではありませんが、シーン内のトライアングルの数は、フレームをレンダリングするのにかかる時間に影響します。MeshPart.RenderFidelity プロパティを
エクセス用のシャドウキャスト - シャドウを処理するのは費用がかかり、シャドウをキャストするためのマップには、高い数と密度のライトオブジェクトが含まれている可能性があります (また、シャドウに影響を与える可能性のある小さなパーツの数と密度) があり、パフォーマンスの問題が発生する可能性があります。
透明効果の高い引き出し - 部分透明のオブジェクトを互いに置くと、エンジンは透明なピクセルを複数回レンダリングし、パフォーマンスに悪影響を与える可能性があります。For more information on identification and fixing this issue, see 透明効果の高い引き出し .
ミトレーション
- 同じメッシュをインスタンスし、メッシュの数を減少すること - すべてのメッシュを同じアセット ID で持つことを確認すると、エンジンはそれらを 1つのドローコールで認識し、レンダリングできます。Make sure to only up
- カールド・オブ・オブジェクト - カールド・オブ・オブジェクトは、最終レンダリングフレームに関連しないオブジェクトのドローコールを処理するプロセスを説明します。デフォルトでは、エンジンはカメラのフィールド
- Class.MeshPart と BasePart は、カメラまたは設定から遠く離れています。
- 室内の環境では、現在使用されていないオブジェクトを隠すルームまたはポータルシステムを実装します。
- レンダリングの忠実度を減少 - レンダリングの忠実度を 自動 または パフォーマンス に設定します。これにより、メッシュが描画する必要があるポリゴンの数が少なくなります。
- 適切なパーツとライトオブジェクトにシャドウキャストを無効にする - シーン内のシャドウの複雑さは、ライトオブジェクトとパーツにシャドウキャストプロパティを選択してオフにすることで減少できます。これは編集時間または実行時にダイナミックに行うことができます。一部の例は次のとおりです:
Class.BasePart.CastShadow プロパティを使用して、小さなパーツでシャドウが見えないようにします。これは、ユーザーのカメラから離れたパーツに適用すると特に効果があります。
移動オブジェクトのシャドウをできるだけオフにします。
オブジェクトがシャドウをキャストする必要がない場合、Light.Shadows を無効にします。
ライトインスタンスの範囲と角度を制限します。
少なくなる照明インスタンスを使用します。
MicroProfiler スコープ
スコープ | 関連する計算 |
準備と実行 | 全体レンダリング |
/ステージ/計算ライトパフォーマンス | ライトグリッドとシャドウ更新 |
ライトグリッドCPU | ボクセルライトグリッドの更新 |
シャドウマップシステム | シャドーマッピング |
Perform/Scene/UpdateView を実行する | レンダリングとパーティクルの更新の準備 |
Perform/Scene/RenderView パフォーム/シーン/レンダリングビュー | レンダリングと投稿処理 |
ネットワークとレプリケーション
ネットワークとレプリケーションは、データがサーバーと接続されたクライアント間で送信されるプロセスを説明します。クライアントとサーバー間での情報はすべてフレームごとに送信されますが、より大きな量の情報はより多くのコンピュート時間が必要になります。
一般的な問題
過度なリモートトラフィック - 大量のデータを RemoteEvent または RemoteFunction オブジェクトを通じて送信すると、フレームごとに処理する必要があるパケットの量が大きくなりすぎる可能性があります。コモンなミスは以下のとおりです:
- レプリケートする必要がないフレームごとにデータをレプリケートします。
- スロットルを制御するメカニズムなしで、ユーザーの入力に基づくデータをレプリケートします。
- 必要なよりも多くのデータを取得しています。たとえば、プレイヤーのインベントリ全体を取得するなど、アイテムを購入するときにアイテムの詳細ではなく、プレイヤーの全体を取得することです。
サーバーのデータモデルに変更が行われると、接続されたクライアントにレプリケートされます。これにより、サーバー上でマップなどの大きなインスタンスを作成および削除できます。 - ランタイムにマップなどの大きなインスタンスを作成および削除すると、ネットワークが非常に重いことになります。
ここのコモンな悪用者は、リグのアニメーションエディタプラグインによって保存された複雑なアニメーションデータです。これらがゲームが公開される前に削除されないと、大量のデータが不要なもので重複されます。
サーバー側の TweenService - 如果 TweenService を使用してオブジェクトサーバー側をツイーンする場合、ツイーンされたプロパティはすべてのクライアントにフレームごとにレプリケートされます。これにより、ツイーンがクライアントのラテンスに対応するためにジッタリーになるだけ
ミトレーション
次のタクティクスを使用して、必要ないレプリケーションを減少できます:
- リモートイベントを通じて大量のデータを一度に送信するのではなく、必要なデータを下の周波数で送信すること。たとえば、キャラクターの状態の場合は、フレームごとではなく、その変更ごとにレプリケートします。 * 複雑なインスタンスツリーをチャンクアップしてマップのように読み込み、ワークを複製することを複数のフレームで分散するようにします。 * アニメーションメタデータをクリーンアップする 、特にリグのアニメーションディレクトリーをインポート後に。
- サーバーがインスタンスを作成する必要がない場合に限定的なインスタンスの複製 、特にサーバーがインスタンスを作成する必要がない場合に限定的なインスタンスの複製を行う必要があります。これには以下が含まれます:
- 爆発や魔法の呪文のようなビジュアルエフェクト。サーバーは、結果を決定するために場所を知る必要があり、クライアントはビジュアルをローカルに作成できます。
- 1人称アイテムビューモデル。
- サーバーではなくクライアントのオブジェクトをツイーンします。
MicroProfiler スコープ
スコープ | 関連する計算 |
プロセスパケット | イベントの招待やプロパティの変更など、入ходяネットワークパケットを処理するプロセス |
バンドウィドを割り当て、送信者を実行する | サーバーに関連する出向イベント |
アセットメモリ使用
クリエーターがクライアントのメモリ使用を改善するために利用可能な最高のインパクトメカニズムは、インスタンスストリーミングを有効にすることです。
インスタンスストリーミング
インスタンスストリーミングは、必要ないデータモデルのパーツを選択して読み込み、メモリープレッシャーによるクライアントの崩壊を防ぐためのクライアントの能力を向上させます。
メモリーの問題に遭遇し、インスタンスストリーミングを無効にしている場合は、エクスペリエンスを更新してサポートして、特に 3D 世界が大きい場合を考慮してください。インスタンスストリーミングは 3D 空間の距離に基づいているので、大きな世界は自然にそれからより多くの利益を得ます。
インスタンスストリーミングが有効になっている場合は、それの攻撃的性を増加させることができます。たとえば、考慮してください:
- 持続的な StreamingIntegrity の使用を減少する。
- ストリーミング範囲を減少 。
ストリーミングオプションとその利点については、ストリーミングプロパティ を参照してください。
他の一般的な問題
- アセットの複製 - 共通のミスは、同じアセット ID を複数回アップロードすることです。これにより、同じコンテンツがメモリに複数回ロードされる可能性があります。
- 過剰なアセットボリューム - アセットが同じでない場合でも、同じアセットを再使用してメモリを節約する機会を逃す場合があります。
- オーディオファイル - オーディオファイルは、特にエクスペリエンスの一部をクライアントに一度に読み込むことで、メモリ使用に驚く貢献をする可能性があります。たとえば、オーディオファイル をクライアントに一度に読み込むと、メモリ使用率が一気に上昇します。For strategies, see 読み込み時間 .
- 高解像度テクスチャー - テクスチャのサイズに関連なく、グラフィックスメモリの使用量はテクスチャの数のピクセルによって変化します。
- たとえば、1024x1024ピクセルのテクスチャは、512x512テクスチャのグラフィックメモリを 4 倍に消費します。
- Roblox にアップロードされた画像は、固定形式に変換されますので、少なくなるビトあたりのメモリーの利点はありません。同様に、画像をカラーモデルに関連付けられた画像をアップロードすると、ディスクのメモリー使用率が減少する可能性がありま
- グラフィックステクスチャ カテゴリを デベロッパーコンソール で拡張すると、特定のテクスチャのグラフィックメモリ使用量を識別できます。
ミトレーション
- アセットのアップロードは 1 回だけ - 同じアセット ID をオブジェクト間で再使用し、特にメッシュやイメージが複数回アップロードされていないことを確認します。
- 複製されたアセットを検索して修正する - 異なるIDで複数回アップロードされた同じメッシュパーツとテクスチャを検索します。
- 似ているアセットを自動的に検出する API はありませんが、場所に置くすべての画像アセット ID を集め、スクリプトでダウンロードし、外部の比較ツールを使用して比較してください。
- メッシュパーツの場合、最善の戦略はユニークなメッシュ ID を取得し、サイズごとに単一のメッシュを手動で識別することです。
- 別々の色にテクスチャを使用する代わりに、単一のテクスチャをアップロードし、SurfaceAppearance.Color プロパティを使用して、色のグレードを適用します。
- マップごとにアセットを別々にインポートすることができます。 - 通常、マップ全体を一度にインポートするのではなく、マップのアセットを個々にインポートして再構築することができます。3D インポータ
- 画像のピクセルを限定する を、必要な量以上に拡大することはありません。画面上の大きな領域を占有していない場合、通常は最大 512x512ピクセルが必要です。ほとんどの小さな画像は、256x256ピクセル以下である必要があります。
- トリミングシートを使用することで、3D マップでの最大テクスチャ再利用を確認します。For steps and examples on how to create trim sheets, see トリミングシートの作成 .
読み込み回数
多くのエクスペリエンスはカスタムロード画面を実装し、ContentProvider:PreloadAsync() メソッドを使用してアセットをリクエストして、画像、サウンド、メッシュをバックグラウンドでダウンロードします。
このアプローチの利点は、ポップアップなしでエクスペリエンスの重要な部分を完全に読み込むことができることです。ただし、コモンなミスは、このメソッドを使用しすぎて、実際に必要なよりも多くのアセットをプレロードすることです。
悪用の例は、全体のWorkspace をロードすることです。これは、テクスチャのポップインを防ぐことができますが、ロード時間が大幅に長くなります。
代わりに、ContentProvider:PreloadAsync() のみを必要な状況で使用し、これには以下が含まれます:
- ロード画面のイメージ。
- ボタンの背景やアイコンなど、エクスペリエンスメニューにある重要な画像をインポートします。
- スタートまたはスポーンエリアの重要なアセット。
大量のアセットを読み込む必要がある場合は、 スキップ読み込み ボタンを提供することをお勧めします。