このページでは、一般的なパフォーマンス問題とそれらを軽減するためのベストプラクティスが説明されています。
脚本計算
Luau コードの高コストの操作は処理に時間がかかり、フレームレートに影響を与える可能性があります。並行して実行されていない限り、Luau コードは同期して実行され、スレッドを返す関数に出会うまでメインスレッドをブロックします。
よくある問題
テーブル構造の強度の高い操作 - シリアル化、デシリアライズ、深いクローン化などの複雑な操作は、特に大きなテーブル構造で高いパフォーマンスコストを発生させます。これは特に、これらの操作が再帰的であるか、非常に大きなデータ構造を反復する場合に当てはまります。
高周波イベント - フレームベースのイベントに高価な操作をバインドして、周波数を制限せずに、これらの操作がすべてのフレームで繰り返されることにより、計算時間が不必要に増加することがよくあります。これらのイベントには以下が含まれます:
軽減
- RunServiceイベントでコードをスパーセブルに呼び出し、高頻度の呼び出しが必須の場合にのみ使用を制限します (例えば、カメラを更新する)。ほとんどの他のコードを他のイベントで実行するか、ループで少し menos 頻度で実行できます。
- task.wait() を使用して、大きなまたは高価なタスクを分割して、作業を複数のフレームに分散します。
- 不必要に高価な操作を識別し最適化し、データモデルにアクセスする必要がない計算的に高価なタスクに マルチスレッド を使用します。
- 特定のサーバー側のスクリプトは、ネイティブコード生成、スクリプトをマシンコードではなくバイトコードにコンパイルするシンプルなフラグから恩益を受けることができます。
マイクロプロファイラスコープ
範囲 | 関連する計算 |
運行サービス.PreRender | プリレンダリングイベントで実行されるコード |
運行サービス.PreSimulation | ステップイベントで実行するコード |
運用サービス。PostSimulation | ハートビートイベントで実行されるコード |
運行サービス.ハートビート | ハートビートイベントで実行されるコード |
MicroProfiler を使用してスクリプトをデバッグするための詳細は、debug ライブラリを参照してください、これにはタグ付きの特定のコードとさらに特定性を増やす機能が含まれています、例えば debug.profilebegin や debug.profileend など。スクリプトによって呼ばれる多くの Roblox API メソッドも、有用なシグナルを提供できる自身の関連するマイクロプロファイラータグを持っています。
スクリプトメモリ使用量
メモリ漏れは、ゴミ箱コレクターが使用していないときに適切にリリースできないメモリを消費するスクリプトを書いたときに発生する可能性があります。リークは、クライアントセッションははるかに短いのに対して、サーバー上では連続して何日もオンラインになることができるため、特に普遍的です。
次のメモリ値は、 開発者コンソール で、さらなる調査が必要な問題を示すことができます:
- LuaHeap - 高いまたは増加する消費は、メモリ漏れを示唆します。
- インスタンス数 - 一貫して増加するインスタンス数は、コード内のいくつかのインスタンスへの参照が収集されていないことを示唆しています。
- PlaceScriptMemory - メモリ使用のスクリプトブレイクダウンでスクリプトを提供します。
よくある問題
接続を残して接続された状態にする - エンジンは、インスタンスに接続されたイベントや、接続されたコールバック内で参照された値を決してゴミ箱に格納しないそのため、イベントとコードのアクティブな接続、接続されたインスタンス、接続された関数、および参照された値は、イベントが発射された後でも、メモリガベージコレクターの範囲外にあります。
インスタンスに属するイベントが切断されても、所属するインスタンスが破棄されても、一般的な間違いは、これが Player オブジェクトに適用されると思い込むことです。ユーザーがエクスペリエンスを終了すると、エンジンは自動的に代表者の Player オブジェクトとキャラクターモデル、およびキャラクターモデルの下の Player オブジェクトやキャラクターモデルを破壊しません。スクリプトで切断しない限り、Player.CharacterAdded などのキャラクターモデルの下のオブジェクトやキャラクターモデルは、メモリを消費し続けます。これにより、何百ものユーザーが体験に参加して退出するにつれて、サーバー上で非常に大きなメモリリークが発生する可能性があります。
テーブル - 必要なくなったときにオブジェクトをテーブルに挿入しても削除しないことで、特にユーザーデータを追跡するテーブルで不必要なメモリ消費が発生します。たとえば、次のコードサンプルでは、ユーザーが参加するたびにユーザー情報を追加するテーブルを作成します:
例題local playerInfo = {}Players.PlayerAdded:Connect(function(player)playerInfo[player] = {} -- いくつかの情報end)必要がなくなったときにこれらのエントリを削除しないと、テーブルのサイズが拡大し、セッションに参加するユーザーが増えるにつれてメモリが消費されます。このテーブルを反復するコードも、テーブルのサイズが大きくなるにつれて、計算コストが上昇します。
軽減
メモリ漏れを防ぐために使用されたすべての値をクリアするには:
すべての接続を切断する - コードベースを通じて、次のパスのいずれかを介して各接続がクリーンアップされることを確認します:
- 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)
物理計算
過度な物理シミュレーションは、サーバーとクライアントの両方でフレームごとの計算時間が増加する主な原因になる可能性があります。
よくある問題
過剰な物理時間ステップ頻度 - デフォルトでは、ステップ行動は 適応モード で、物理ステップが 60 Hz、120 Hz、または 240 Hz であり、物理メカニズムの複雑さに応じています。
物理の精度を向上させた固定モードも利用可能であり、すべての物理アセンブリが 240 Hz (フレームごとに 4 回) でステップするように強制します。これにより、各フレームで大幅に多くの計算が行われます。
シミュレーションされたオブジェクトの複雑度が多すぎる - シミュレーションされる 3D アセンブリの数が多いほど、物理計算は各フレームで長くなります。しばしば、エクスペリエンスには、必要ではないオブジェクトがシミュレートされたり、必要以上の制限と接合があるメカニズムが存在することがあります。
過度に精密な衝突検出 - メッシュパーツには、衝突を検出するための CollisionFidelity プロパティがあり、パフォーマンスの影響レベルが異なるさまざまなモードを検出できます。メッシュパーツの精密な衝突検出モードには、最も高価なパフォーマンスコストが発生し、エンジンの計算に時間がかかります。
軽減
シミュレーションが必要ないアンカーパーツ - 静的NPCなど、物理によって駆動する必要がないすべてのパーツをアンカーする
適応的な物理ステッピングを使用 - 適応ステッピングは、物理メカニズムの物理計算率を動的に調整し、物理更新が少しの場合に行われる頻度を減らすことができる
メカニズムの複雑さを減らす * 可能であれば、アセンブリ内の物理制約またはジョイントの数を最小限に抑えます。
- メカニズム内の自己衝突量を減少させるために、限界または衝突禁止制限をラグドールの肢に適用して、お互いに衝突しないようにする。
メッシュの精密な衝突忠実度の使用を減らす * ユーザーがほとんど差を気づかない小さな非インタラクティブオブジェクトの場合は、ボックスの忠実度を使用します。
小型から中型のオブジェクトの場合、形状に応じてボックスまたは船体の忠実度を使用します。
大規模で非常に複雑なオブジェクトの場合、可能な限り目に見えないパーツを使用してカスタムコリジョンを構築します。
衝突が必要ないオブジェクトの場合、衝突を無効にしてボックスまたは船体の忠実度を使用し、衝突ジオメトリはまだメモリに保存されているためです。
精度とパフォーマンス要件のバランスを取る衝突信頼性オプションを選択する方法の詳細な解説は、物理とレンダリングパラメータを設定 を参照してください。
マイクロプロファイラスコープ
範囲 | 関連する計算 |
物理ステップ | 全体の物理計算 |
世界ステップ | 各フレームで取られる決定的な物理ステップ |
物理メモリ使用量
物理移動と衝突検出にはメモリが消費されます。メッシュパーツには CollisionFidelity プロパティがあり、メッシュの衝突境界を評価するために使用されるアプローチを決定します。
一般的な問題
デフォルトの精密な衝突検出モードと精密な衝突検出モードは、低精度の衝突形状を持つ他の 2 つのモードよりも大幅に多くのメモリを消費します。
物理パーツ の下でメモリ使用量が高いレベルになる場合、エクスペリエンス内のオブジェクトの 衝突忠実度 を減少させる必要があるかもしれない。
軽減方法
衝突精度に使用されるメモリを減少するには:
- CollisionFidelity 設定を使用して、衝突の信頼性を低下させます。Box は最も低いメモリオーバーヘッドを持ち、Default と Precise は一般的に高価です。
- 一般的に、小さな固定部品の衝突精度を Box に設定することは安全です。
- 非常に複雑な大きなメッシュの場合、ボックスコリジョンの精度で小さなオブジェクトから自分の衝突メッシュをビルドしたいかもしれません。
ヒューマノイド
Humanoid は、プレイヤーとプレイヤー以外のキャラクター(NPC)に幅広い機能を提供するクラスです。強力ではありますが、Humanoid には大きな計算コストが伴います。
よくある問題
- NPC ですべての HumanoidStateTypes を有効にしておく - 特定の HumanoidStateTypes を有効にしておくと、パフォーマンスコストが発生します。NPCに必要ないものはすべて無効にします。たとえば、NPCがはしごを登るつもりがない限り、Climbing 状態を無効にすることは安全です。
- ヒューマノイドを頻繁に使用してモデルをインスタンス化、修正、リスポーンする * これはエンジンが処理するのに時間がかかる可能性があり、特にこれらのモデルが レイヤー服装 を使用している場合。これは、アバターが頻繁にリスポーンする経験でも特に問題があります。
- マイクロプロファイラ では、長い 更新無効化速いクラスター タグ(4ms 以上)は、アバターのインスタンス化/修正が過剰な無効化をトリガーしているシグナルであることが多い
- ヒューマノイドを使用して、必要ない場合 - 通常移動しない静的NPCは、Humanoid が必要ない。
- サーバーから大量の NPC にアニメーションを再生する - サーバー上で実行される NPC のアニメーションは、サーバー上でシミュレートし、クライアントにレプリケートする必要があります。これは不必要なオーバーヘッドになる可能性があります。
軽減
- クライアントで NPC アニメーションを再生する - NPC の数が多いエクスペリエンスでは、クライアント上で Animator を作成し、アニメーションをローカルで実行することを検討してください。これにより、サーバーの負荷が軽減され、不必要なレプリケーションの必要性が減ります。また、追加の最適化 (例: キャラクターの近くにいる NPC のアニメーションのみを再生するなど) も可能にします。
- ヒューマノイドの代替手段を使用する - NPCモデルには必ずしもヒューマノイドオブジェクトを含める必要はありません。
- 静的 NPC の場合は、移動する必要はないがアニメーションを再生するだけで十分なので、単純な AnimationController を使用します。
- NPCを移動するには、NPCの複雑さに応じて、独自の移動コントローラを実装し、アニメーションには AnimationController を使用することを検討してください。
- 使用されていないヒューマノイド状態を無効にする - 使用 Humanoid:SetStateEnabled() を使用して、各ヒューマノイドに必要な状態のみを有効にします。
- 頻繁にリスポーンするプールNPCモデル - NPCを完全に破壊するのではなく、NPCを非アクティブなNPCプールに送信します。この方法では、新しい NPC がリスポーンする必要があるとき、プールから NPC の 1つを再起動するだけでよいです。このプロセスは、キャラクターがインスタンス化する必要がある回数を最小限に抑える「プール化」と呼ばれます。
- ユーザーが近くにいるときだけNPCをスポーンする - ユーザーが範囲内にいないときにNPCをスポーンしないでください、そしてユーザーが範囲を離れるときにそれらを排除する
- インスタンス化後、アバター階層に変更を加えないようにする - アバター階層に特定の修正を加えると、パフォーマンスに大きな影響があります。いくつかの最適化が利用可能です:
- カスタムプロシージャルアニメーションの場合、JointInstance.C0 および JointInstance.C1 プロパティを更新しないでください。代わりに、Motor6D.Transform プロパティを更新してください。
- アバターに任意の BasePart オブジェクトを付ける必要がある場合は、アバターの階層外で行います Model .
マイクロプロファイラスコープ
範囲 | 関連する計算 |
ステップ人形oid | ヒューマノイド制御と物理学 |
步驟アニメーション | ヒューマノイドとアニメータのアニメーション |
無効化された高速クラスターを更新 | アバターのインスタンス化または修正と関連する |
レンダリング
クライアントが各フレームで費やす時間の大部分は、現在のフレームでシーンをレンダリングすることです。サーバーはレンダリングを行わないため、このセクションはクライアント専用です。
呼び出しを引き出す
ドローコールは、エンジンからGPUへのレンダリングの指示のセットです。ドローコールには大きなオーバーヘッドがあります。一般的に、フレームごとのドローコールが少ないほど、フレームのレンダリングに費やされる計算時間が少なくなります
Studio の レンダリング統計 > タイミング アイテムで、現在どれくらい多くのドローコールが発生しているかを確認できます。クライアントで レンダリング統計を表示 するには、ShiftF2 を押します。
特定のフレームでシーンに描画する必要のあるオブジェクトが多いほど、GPU による描画呼び出しが増加します。しかし、Roblox エンジンは、同じテクスチャ特性を持つ同一のメッシュを単一のドローコールに継承するプロセスである instancing を使用します。特に、同じ MeshId の複数のメッシュが、次の場合に単一のドローコールで処理される:
- 両方の SurfaceAppearance と MeshPart.TextureID が存在しないとき、材料は同じです。
他の一般的な問題
過剰なオブジェクト密度 - 大量のオブジェクトが高密度で集中している場合、このシーンの領域をレンダリングするには、より多くのドローコールが必要になります。マップの特定の部分を見るとフレームレートが低下するのを発見した場合、これはこの領域のオブジェクト密度が高すぎることを示す良いシグナルです。
デカール、テクスチャ、パーティクルなどのオブジェクトはバッチがうまくいかず、追加のドローコールを発生させます。シーンでこれらのオブジェクトタイプに特別な注意を払います。特に、プロパティが ParticleEmitters に変更されると、パフォーマンスに大きな影響を与える可能性があります。
インスタンス機会を逃した - よく、シーンには同じメッシュが複数回複製されていますが、メッシュの各コピーには異なるメッシュまたはテクスチャアセットIDが含まれています。これによりインスタンス化が防止され、不必要なドローコールが生じる可能性があります。
この問題の一般的な原因は、個々のアセットを Roblox にインポートして組み立て、その後ポストインポートで複製するのではなく、1度に全体のシーンをインポートするときです。
過剰なオブジェクト複雑性 - ドローコールの数と同じくらい重要ではありませんが、シーンにあるトライアングルの数は、フレームがレンダリングにどれほど時間がかかるかに影響します。非常に大きな数の非常に複雑なメッシュを持つシーンは、多すぎるメッシュに プロパティを設定したシーンと同様、一般的な問題です。
過剰なシャドウキャスト - シャドウの処理は高コストのプロセスであり、シャドウを投射する光オブジェクトの数と密度が多いマップ (または、シャドウに影響を受ける小さなパーツの数と密度が多いマップ) は、パフォーマンスの問題が発生する可能性が高い。
高透明度オーバードライブ - 部分的な透明度を持つオブジェクトを近づけると、エンジンが重複するピクセルを複数回レンダリングするようになり、パフォーマンスに悪影響を及ぼす可能性があります。この問題の識別と修正に関する詳細は、レイヤーの透明性を削除する を参照してください。
軽減
- 同じメッシュをインスタンス化し、ユニークなメッシュの数を減らす - すべての同じメッシュに同じベースアセットIDを持たせることで、エンジンは単一のドローコールで認識してレンダリングできます。マップに各メッシュをアップロードするのは一度だけで、後で Studio で複製して再使用するので、エンジンによって同じメッシュが異なるコンテンツIDを持ち、ユニークなアセットとして認識される可能性がある大きなマップ全体をインポートするのではないことを確認してください。パッケージはオブジェクトの再利用に役立つメカニズムです。
- 選択 - 選択は、最終レンダリングフレームに含まれないオブジェクトのドローコールを削除するプロセスを説明します。デフォルトでは、エンジンはカメラの視野外のオブジェクトのドローコールをスキップします(フラストムカッリング)が、他のオブジェクトによって視界から隠されたオブジェクトのドローコールはスキップしません(閉塞カッリング)シーンに多くのドローコールがある場合は、次の一般的な戦略を動的に実行時に実装して、毎フレームに自分の追加選択を実装することを検討してください:
- 室内環境の場合、現在アクティブなユーザーによって占有されていないオブジェクトを隠すルームまたはポータルシステムを実装します。
- レンダリング精度の削減 - レンダリング精度を 自動 または パフォーマンス に設定します。これにより、メッシュがより複雑な代替に戻るのを防ぎ、描画する必要があるポリゴンの数を減らすことができます。
- 適切なパーツやライトオブジェクトでシャドウキャストを無効にする - シーンのシャドウの複雑さは、ライトオブジェクトやパーツのシャドウキャストプロパティを選択的に無効にすることで減少できます。これは、編集時または実行時に動的に行うことができます。いくつかの例は次のとおり:
BasePart.CastShadow プロパティを使用して、シャドウが見える可能性が低い小さなパーツでシャドウキャストを無効にします。特に、ユーザーのカメラから遠く離れたパーツにのみ適用するときに効果的です。
可能であれば、移動オブジェクトの影を無効にします。
オブジェクトがシャドウをキャストする必要がないライトインスタンスで Light.Shadows を無効にする
光インスタンスの範囲と角度を制限する。
ライトインスタンスを少なく使用する。
マイクロプロファイラスコープ
範囲 | 関連する計算 |
準備して実行 | 全体のレンダリング |
パフォーム/シーン/ComputeLightingPerform | ライトグリッドとシャドウのアップデート |
ライトグリッドCPU | ボクセルライトグリッドのアップデート |
シャドーマップシステム | シャドーマッピング |
実行/シーン/アップデートビュー | レンダリングとパーティクルアップデートの準備 |
実行/シーン/レンダリングビュー | レンダリングと後処理 |
ネットワークとリプリケーション
ネットワーキングとレプリケーションでは、データをサーバーと接続されたクライアント間で送信するプロセスを説明します。情報は、フレームごとにクライアントとサーバー間で送信されますが、より多くの情報には、より多くの計算時間が必要です。
よくある問題
過剰なリモートトラフィック - RemoteEvent または RemoteFunction オブジェクトを大量に送信したり、非常に頻繁に呼び出したりすると、フレームごとに受信したパケットを処理するために大量のCPU時間が消費される可能性があります。一般的な間違いには以下が含まれます:
- 複製する必要がないすべてのフレームのデータを再複製する。
- 制限を課すメカニズムなしで、ユーザーの入力に対するデータをレプリケートする
- 必要以上のデータを送信しています。たとえば、購入したアイテムの詳細ではなく、プレイヤーの全在庫を送信することなど。
複雑なインスタンスツリーの作成または削除 - サーバー上のデータモデルに変更が行われたとき、接続されたクライアントに複製されます。これは、実行時にマップのような大規模なインスタンス階層を作成して破壊することがネットワーク密度が高い可能性があることを意味します。
ここでは、アニメーションエディタプラグインによってリグに保存された複雑なアニメーションデータが一般的な罪人です。ゲームが公開されてアニメーションモデルが定期的にクローンされる前にこれらが削除されない場合、大量の不必要なデータが複製されます。
サーバー側の TweenService - TweenService がオブジェクトサーバー側でトレンドを行うとき、トレンドされたプロパティは各クライアントに毎フレーム毎にレプリケートされます。これにより、クライアントの遅延が変動するたびにティーンが緊張してしまうだけでなく、不必要なネットワークトラフィックが大量に発生します。
軽減
不必要なレプリケーションを減らすために次の戦略を使用できます:
- リモートイベントを通じて一度に大量のデータを送信しないようにする .代わりに、より低い頻度で必要なデータのみを送信します。たとえば、キャラクターの状態の場合、すべてのフレームではなく変更するときにそれを複製します。
- 複雑なインスタンスツリーをマップとしてチャンクアップし、それらを各フレームに分けて配布するために、ピースごとにロードする * アニメーションメタデータをクリーンアップする 、特にリグのアニメーションディレクトリ、インポート後
- 不必要なインスタンスレプリケーションを制限する 、特に、サーバーが作成中のインスタンスについて知る必要がない場合これには含まれます:
- 爆発や魔法の呪文爆発などのビジュアル効果。サーバーは結果を決定するために場所を知る必要があり、クライアントはローカルでビジュアルを作成できます。
- 第一人称アイテムビューモデル。
- サーバーではなく、クライアント上の潜在オブジェクト。
マイクロプロファイラスコープ
範囲 | 関連する計算 |
プロセスパケット | イベント呼び出しやプロパティ変更など、受信ネットワークパケットの処理 |
帯域を割り当てて送信者を実行する | サーバーに関連するアウトバウンドイベント |
アセットメモリ使用量
クリエイターがクライアントのメモリ使用量を改善するために利用できる最も影響力のあるメカニズムは、インスタンスストリーミング を有効にすることです。
インス턴スストリーミング
インスタンスストリーミングは、必要ないデータモデルの一部を選択的にロードし、結果として負荷時間が大幅に短縮され、メモリプレッシャーがかかったときにクライアントがクラッシュを防ぐ能力が向上することがあります。
メモリの問題に直面し、インスタンスストリーミングが無効になっている場合は、特に 3D ワールドが大きい場合、エクスペリエンスを更新してサポートすることを検討してください。インスタンスストリーミングは、3D 空間の距離に基づいているので、より大きな世界は自然にそれより多くの利益を得ます。
インスタンスストリーミングが有効になっている場合、その攻撃性を高めることができます。たとえば、考えてみましょう:
- 永続的な ストリーミングインテグリティ の使用を減少する。
- ストリーミング範囲 を減少する。
ストリーミングオプションとそのメリットに関する詳細は、ストリーミングプロパティ を参照してください
他の一般的な問題
- アセット複製 - 一般的な間違いは、同じアセットを複数回アップロードして、異なるアセットIDに結果することです。これにより、同じコンテンツが複数回メモリにロードされる可能性があります
- 過剰なアセット量 - アセットが同じではない場合でも、同じアセットを再使用してメモリを節約する機会を逃すことがあります。
- オーディオファイル - オーディオファイルは、特にエクスペリエンスの一部のみを必要とするのではなく、すべてのオーディオファイルをクライアントに一度にロードすると、メモリ使用に驚くべき貢献者になる可能性があります。戦略については、ロード時間 を参照してください。
- 高解像度テクスチャ - テクスチャのグラフィックメモリ消費は、ディスク上のテクスチャのサイズとは無関係ですが、テクスチャのピクセル数に関連しています。
- たとえば、1024x1024 ピクセルテクスチャは、512x512 テクスチャのグラフィックメモリの 4 倍を消費します。
- Roblox にアップロードされた画像は、固定形式に変換されるため、ピクセルごとに少ないバイト数のカラーモデルに関連付けられた画像をアップロードするメモリメリットはありません。同様に、アップロードまたはアルファチャンネルを画像から削除する前に画像を圧縮するか、必要としない画像からアルファチャンネルを削除すると、ディスク上の画像サイズが減少する可能性がありますが、改善されることはありません、またはほんの少しメモリ使用量が改善されます。エンジンは、いくつかのデバイスでテクスチャ解像度を自動的にダウンスケールしますが、ダウンスケールの範囲はデバイスの特性によります、および過剰なテクスチャ解像度はまだ問題を引き起こす可能性があります。
- グラフィックメモリの消費量を特定のテクスチャに割り当てるには、 グラフィックテクスチャ カテゴリを拡張して、 開発者コンソール で、
軽減
- アセットのアップロードは1回のみ - オブジェクト間で同じアセットIDを再使用し、特にメッシュや画像などの同じアセットが複数回別々にアップロードされないようにします。
- 重複アセットを見つけて修正する - 異なるIDで複数回アップロードされた同じメッシュパーツとテクスチャを検索します。
- アセットの類似性を自動的に検出する APIはありませんが、場所にすべての画像アセットIDを収集し(手動またはスクリプトで)、ダウンロードし、外部の比較ツールを使用して比較することができます。
- メッシュパーツの場合、最良の戦略は、ユニークなメッシュ ID を取得し、サイズで分類して手動で複製を識別することです。
- 異なる色に別々のテクスチャを使用するのではなく、1つのテクスチャをアップロードし、SurfaceAppearance.Color プロパティを使用して、それにさまざまな色合いを適用します。
- マップでアセットを個別にインポートする - 一度に全体のマップをインポートするのではなく、マップで個々のアセットをインポートし、再構築し、再構築します。3Dインポーターは、メッシュのデュープリケーションを行わないので、大きなマップを多くの個別のフロアタイルでインポートした場合、それらのタイルはそれぞれが別のアセットとしてインポートされます(デュープリケーションであっても)。これにより、各メッシュが個別に扱われ、メモリとドローコールが消費されるため、ライン全体でパフォーマンスとメモリの問題が発生する可能性があります。
- 画像のピクセルを必要量以上に制限する 必要があります。画像がスクリーン上の大量の物理スペースを占有していない限り、通常最大 512x512 ピクセルが必要です。ほとんどの小さな画像は、256x256 ピクセルより小さいでしょう。
- トリムシートを使用する ことで、3Dマップで最大のテクスチャ再利用を保証できます。トリムシートを作成する手順と例は、トリムシートの作成 を参照してください。
ロード時間
多くのエクスペリエンスは、カスタムロード画面を実装し、ContentProvider:PreloadAsync() メソッドを使用してアセットをリクエストして、画像、サウンド、およびメッシュがバックグラウンドでダウンロードされます。
このアプローチのメリットは、ポップインせずにエクスペリエンスの重要な部分が完全にロードされるようにできることです。しかし、一般的な間違いは、実際に必要なものより多くのアセットをプレロードするために、このメソッドを過剰に使用することです。
悪い習慣の例は、全体Workspace をロードすることです。テクスチャのポップインを防ぐ可能性はありますが、ロード時間が大幅に増加します。
代わりに、必要な状況にのみ ContentProvider:PreloadAsync() を使用し、それには以下が含まれます:
- ロード画面に表示される画像。
- エクスペリエンスメニューに表示される重要な画像、例えばボタンの背景やアイコン。
- 開始またはスポーンエリアに重要なアセット。
大量のアセットをロードする必要がある場合、 ロードをスキップする ボタンを提供することをお勧めします。