Unity のパフォーマンスに関する推奨事項Performance recommendations for Unity

この記事は、「 mixed reality のパフォーマンスに関する推奨事項」で説明されている説明に基づいていますが、Unity エンジン環境に固有の学習に重点を置いています。This article builds on the discussion outlined in performance recommendations for mixed reality but focuses on learnings specific to the Unity engine environment.

また、開発者がUnity の推奨される環境設定を確認することを強くお勧めします。It is also highly advisable that developers review the recommended environment settings for Unity article. この記事には、パフォーマンスに優れた Mixed Reality アプリの構築に関して、最も重要なシーン構成の一部が含まれています。This article has content with some of the most important scene configurations in regards to building performant Mixed Reality apps. これらの推奨設定の一部も下に強調表示されています。Some of these recommended settings are highlighted below as well.

Unity でプロファイルする方法How to profile with Unity

Unity には、特定のアプリの貴重なパフォーマンスの洞察を収集するための優れたリソースである Unity Profiler が組み込まれています。Unity provides the Unity Profiler built-in which is a great resource to gather valuable performance insights for your particular app. エディターでプロファイラーを実行できますが、これらのメトリックは実際のランタイム環境を表すものではないため、このような結果は慎重に使用する必要があります。Although one can run the profiler in-editor, these metrics do not represent the true runtime environment and thus, results from this should be used cautiously. デバイスでの実行中に、正確で実用的な洞察を得るために、アプリケーションをリモートでプロファイリングすることをお勧めします。It is recommended to remotely profile your application while running on device for most accurate and actionable insights. さらに、Unity のフレームデバッガーは、利用するための非常に強力な洞察ツールでもあります。Further, Unity's Frame Debugger is also a very powerful and insight tool to utilize.

Unity は、次のことに関する優れたドキュメントを提供します。Unity provides great documentation for:

  1. Unity profiler をリモートで UWP アプリケーションに接続する方法How to connect the Unity profiler to UWP applications remotely
  2. Unity Profiler でパフォーマンスの問題を効果的に診断する方法How to effectively diagnose performance problems with the Unity Profiler

注意

Unity プロファイラーが接続され、GPU プロファイラーを追加した後 (「Profiler を右上隅に追加する」を参照してください)、プロファイラーの途中で CPU & GPU でどのくらいの時間がかかっているかを確認できます。With the Unity Profiler connected and after adding the GPU profiler (see Add Profiler in top right corner), one can see how much time is being spent on the CPU & GPU respectively in the middle of the profiler. これにより、開発者は、アプリケーションが CPU または GPU で制限されている場合に、簡単に近似できます。This allows the developer to get a quick approximation if their application is CPU or GPU bounded.

Unity CPU と GPU

CPU パフォーマンスに関する推奨事項CPU performance recommendations

以下のコンテンツでは、特に Unity & C#開発を対象とした、より詳細なパフォーマンスプラクティスについて説明します。The content below covers more in-depth performance practices, especially targeted for Unity & C# development.

キャッシュ参照Cache references

初期化時に、関連するすべてのコンポーネントとオブジェクトへの参照をキャッシュすることをお勧めします。It is best practice to cache references to all relevant components and GameObjects at initialization. これは、 getcomponent<T > () などの繰り返し関数呼び出しの方が、ポインターを格納するためのメモリコストに比べてかなりコストが高くなるためです。This is because repeating function calls such as GetComponent<T>() are significantly more expensive relative to the memory cost to store a pointer. これは、非常に頻繁に使用されるカメラにも適用されます。This also applies to to the very, regularly used Camera.main. Camera. main は、 実際には findexpensively を使用します。この タグ は、 "maincamera" タグを持つカメラオブジェクトのシーングラフを検索します。Camera.main actually just uses FindGameObjectsWithTag() underneath which expensively searches your scene graph for a camera object with the "MainCamera" tag.

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour
{
    private Camera cam;
    private CustomComponent comp;

    void Start() 
    {
        cam = Camera.main;
        comp = GetComponent<CustomComponent>();
    }

    void Update()
    {
        // Good
        this.transform.position = cam.transform.position + cam.transform.forward * 10.0f;

        // Bad
        this.transform.position = Camera.main.transform.position + Camera.main.transform.forward * 10.0f;

        // Good
        comp.DoSomethingAwesome();

        // Bad
        GetComponent<CustomComponent>().DoSomethingAwesome();
    }
}

注意

GetComponent (string) を避けます。Avoid GetComponent(string)
Getcomponent () を使用する場合、いくつかの異なるオーバーロードがあります。When using GetComponent(), there are a handful of different overloads. 常に型ベースの実装を使用し、文字列ベースの検索オーバーロードは使用しないことが重要です。It is important to always use the Type based implementations and never the string-based searching overload. シーンでの文字列による検索は、型での検索よりもかなりコストがかかります。Searching by string in your scene is significantly more costly than searching by Type.
正常コンポーネント GetComponent (型の型)(Good) Component GetComponent(Type type)
正常T getcomponent<t > ()(Good) T GetComponent<T>()
不良コンポーネント GetComponent (文字列) >(Bad) Component GetComponent(string)>

コストのかかる操作を避けるAvoid expensive operations

  1. LINQの使用を避けるAvoid use of LINQ

    LINQ は非常にクリーンで、読み取りと書き込みが簡単ですが、通常はアルゴリズムを手動で記述するよりもはるかに多くの計算と、特にメモリの割り当てが必要になります。Although LINQ can be very clean and easy to read and write, it generally requires much more computation and particularly more memory allocation than writing the algorithm out manually.

    // Example Code
    using System.Linq;
    
    List<int> data = new List<int>();
    data.Any(x => x > 10);
    
    var result = from x in data
                 where x > 10
                 select x;
    
  2. 共通 Unity ApiCommon Unity APIs

    特定の Unity Api は便利ですが、実行するのは非常にコストがかかります。Certain Unity APIs, although useful, can be very expensive to execute. ほとんどの場合、シーングラフ全体を検索して、一致するオブジェクトの一覧を検索します。Most of these involve searching your entire scene graph for some matching list of GameObjects. これらの操作は、通常、参照をキャッシュするか、問題のあるオブジェクトのマネージャーコンポーネントを実装して実行時に参照を追跡することで回避できます。These operations can generally be avoided by caching references or implementing a manager component for the GameObjects in question to track the references at runtime.

     GameObject.SendMessage()
     GameObject.BroadcastMessage()
     UnityEngine.Object.Find()
     UnityEngine.Object.FindWithTag()
     UnityEngine.Object.FindObjectOfType()
     UnityEngine.Object.FindObjectsOfType()
     UnityEngine.Object.FindGameObjectsWithTag()
     UnityEngine.Object.FindGameObjectsWithTag()
    

注意

SendMessage ()BroadcastMessage () は、すべてのコストで排除する必要があります。SendMessage() and BroadcastMessage() should be eliminated at all costs. これらの関数は、直接の関数呼び出しよりも1,000 倍の速度で実行できます。These functions can be on the order of 1000x slower than direct function calls.

  1. ボックス化に注意してくださいBeware of boxing

    ボックス化は、 C#言語とランタイムの中核となる概念です。Boxing is a core concept of the C# language and runtime. これは、char、int、bool などの値で型指定された変数を参照型の変数にラップするプロセスです。It is the process of wrapping value-typed variables such as char, int, bool, etc. into reference-typed variables. 値型の変数が "ボックス化" されている場合は、マネージヒープに格納されている System.object の内部にラップされます。When a value-typed variable is "boxed", it is wrapped inside of a System.Object which is stored on the managed heap. したがって、ガベージコレクターによって破棄される必要がある場合は、メモリが割り当てられ、最終的にはメモリが割り当てられます。Thus, memory is allocated and eventually when disposed must be processed by the garbage collector. これらの割り当てと割り当て解除には、パフォーマンスコストが発生します。また、多くのシナリオでは不要であるか、低コストの代替手段で簡単に置き換えることができます。These allocations and deallocations incur a performance cost and in many scenarios are unnecessary or can be easily replaced by a less expensive alternative.

繰り返しコードパスRepeating code paths

すべての繰り返し Unity コールバック関数 (Any repeating Unity callback functions (i.e 更新) 1 秒間に何度も実行されるか、またはフレームが非常に慎重に書き込まれる必要があります。Update) that are executed many times per second and/or frame should be written very carefully. ここで高価な操作を行うと、パフォーマンスに大きな影響を与えます。Any expensive operations here will have huge and consistent impact on performance.

  1. 空のコールバック関数Empty callback functions

    以下のコードは、アプリケーション内に残すことができないように見えることがありますが、特にすべての Unity スクリプトがこのコードブロックで自動的に初期化するため、これらの空のコールバックは実際には非常にコストが高くなる可能性があります。Although the code below may seem innocent to leave in your application, especially since every Unity script auto-initializes with this code block, these empty callbacks can actually become very expensive. Unity はアンマネージコードとマネージコードの境界を越えて、UnityEngine コードとアプリケーションコードの間で動作します。Unity operates back and forth over an unmanaged/managed code boundary, between UnityEngine code and your application code. このブリッジに対するコンテキストの切り替えは、実行するものがない場合でもかなりコストがかかります。Context switching over this bridge is fairly expensive even if there is nothing to execute. これは、アプリに空の Unity コールバックを持つコンポーネントを含む100のユーザーオブジェクトがある場合に特に問題になります。This becomes especially problematic if your app has 100's of GameObjects with components that have empty repeating Unity callbacks.

    void Update()
    {
    }
    

注意

Update () は、このパフォーマンスの問題の最も一般的な取り組みですが、次のようなその他の反復的な Unity コールバックは、悪くない場合にも同様の問題になることがあります。FixedUpdate ()、Behaviour ()、OnPostRender "、OnPreRender ()、OnRenderImage () など。Update() is the most common manifestation of this performance issue but other repeating Unity callbacks such as the following can be equally as bad if not worse: FixedUpdate(), LateUpdate(), OnPostRender", OnPreRender(), OnRenderImage(), etc.

  1. フレームごとに1回実行を優先する操作Operations to favor running once per frame

    次の Unity Api は、多くの Holographic アプリで一般的な操作です。The following Unity APIs are common operations for many Holographic Apps. これらの関数の結果は、常に可能であるとは限りませんが、通常は1回計算し、その結果を特定のフレームのアプリケーション全体で再利用することができます。Although not always possible, the results from these functions can very commonly be computed once and the results re-utilized across the application for a given frame.

    a) 一般に、1つのシーンに対して Raycast を処理する専用のシングルトンクラスまたはサービスを用意し、その後、それぞれの Raycast 操作を繰り返すのではなく、他のすべてのシーンコンポーネントで再利用することをお勧めします。成分.a) Generally it is good practice to have a dedicated Singleton class or service to handle your gaze Raycast into the scene and then re-use this result in all other scene components, instead of making repeated and essentially identical Raycast operations by each component. もちろん、アプリケーションによっては、異なるオリジンまたは異なるレイヤーマスクの raycasts が必要になる場合があります。Of course, some applications may require raycasts from different origins or against different LayerMasks.

     UnityEngine.Physics.Raycast()
     UnityEngine.Physics.RaycastAll()
    

    b) Start () または起動 () で参照をキャッシュすることで、Update () のような Unity コールバックを繰り返し実行する場合は、getcomponent () 操作を避けてください。b) Avoid GetComponent() operations in repeated Unity callbacks like Update() by caching references in Start() or Awake()

     UnityEngine.Object.GetComponent()
    

    c) 初期化時にすべてのオブジェクトをインスタンス化し、オブジェクトプーリングを使用して、アプリケーションの実行時にユーザーオブジェクトをリサイクルして再利用することをお勧めします。c) It is good practice to instantiate all objects, if possible, at initialization and use object pooling to recycle and re-use GameObjects throughout runtime of your application

     UnityEngine.Object.Instantiate()
    
  2. インターフェイスと仮想コンストラクトを避けるAvoid interfaces and virtual constructs

    インターフェイスと直接のオブジェクトまたは呼び出し元の仮想関数を使用した関数呼び出しの呼び出しは、直接コンストラクトや直接関数呼び出しを利用するよりもはるかにコストがかかることがあります。Invoking function calls through interfaces vs direct objects or calling virtual functions can often times be much more expensive than utilizing direct constructs or direct function calls. 仮想関数またはインターフェイスが不要な場合は、削除する必要があります。If the virtual function or interface is unnecessary, then it should be removed. ただし、これらのアプローチを利用すると、開発コラボレーション、コードの読みやすさ、およびコードの保守性が簡単になるため、一般に、これらの方法のパフォーマンスが低下します。However, the performance hit for these approaches are generally worth the trade-off if utilizing them simplifies development collaboration, code readability, and code maintainability.

  3. 構造体を値で渡さないようにするAvoid passing structs by value

    クラスとは異なり、構造体は値型であり、関数に直接渡されると、その内容が新しく作成されたインスタンスにコピーされます。Unlike classes, structs are value-types and when passed directly to a function, their contents are copied into a newly created instance. このコピーにより、CPU コストとスタックの追加メモリが追加されます。This copy adds CPU cost as well as additional memory on the stack. 小さい構造体の場合、通常、影響は最小限に抑えられるため、許容されます。For small structs, the effect is usually very minimal and thus acceptable. ただし、すべてのフレームと、大きな構造体を取得する関数を繰り返し呼び出す関数の場合は、可能であれば、参照渡しで渡すように関数定義を変更します。However, for functions repeatedly invoked every frame as well as functions taking large structs, if possible modify the function definition to pass by reference. 詳細情報Learn more here

その他Miscellaneous

  1. 物理Physics

    a) 一般に、物理機能を改善する最も簡単な方法は、物理または1秒あたりの反復回数にかかる時間を制限することです。a) Generally, easiest way to improve physics is to limit the amount of time spent on Physics or the number of iterations per second. もちろん、これによりシミュレーションの精度が低下します。Of course, this will reduce simulation accuracy. Unity のTimeManagerを参照してください。See TimeManager in Unity

    b) Unity の colliders の種類には、さまざまなパフォーマンス特性があります。b) The type of colliders in Unity have widely different performance characteristics. 次の順序では、最もパフォーマンスの高い colliders を左から右へと最もパフォーマンスの低い colliders に一覧表示します。The order below lists the most performant colliders to least performant colliders from left to right. メッシュの Colliders を回避することは、プリミティブな Colliders よりはるかに高価であることを避けることが最も重要です。It is most important to avoid Mesh Colliders which are substantially more expensive than the primitive colliders.

     Sphere < Capsule < Box <<< Mesh (Convex) < Mesh (non-Convex)
    

    詳細については、「 Unity の物理ベストプラクティス」を参照してください。See Unity Physics Best Practices for more info

  2. 動画Animations

    アニメーターコンポーネントを無効にして、アイドル状態のアニメーションを無効にします (game オブジェクトを無効にしても効果はありません)。Disable idle animations by disabling the Animator component (disabling the game object won't have the same effect). ループ内にアニメーターがあるときに値を同じものに設定する設計パターンは避けてください。Avoid design patterns where an animator sits in a loop setting a value to the same thing. この手法にはかなりのオーバーヘッドがあり、アプリケーションに影響はありません。There is considerable overhead for this technique, with no effect on the application. 詳細については、こちらをご覧ください。Learn more here.

  3. 複雑なアルゴリズムComplex algorithms

    アプリケーションで、逆のキネマティック、パス検索などの複雑なアルゴリズムを使用している場合は、より単純なアプローチを見つけたり、パフォーマンスに関連する設定を調整したりします。If your application is using complex algorithms such as inverse kinematics, path finding, etc, look to find a simpler approach or adjust relevant settings for their performance

CPU と GPU のパフォーマンスに関する推奨事項CPU-to-GPU performance recommendations

一般に、CPU と GPU のパフォーマンスは、グラフィックスカードに送信される描画呼び出しに対して行われます。Generally, CPU-to-GPU performance comes down to the draw calls submitted to the graphics card. パフォーマンスを向上させるには、描画呼び出しが戦略的に再構築 ) 、最適な結果を得るためにb) 必要があります。To improve performance, draw calls need to be strategically a) reduced or b) restructured for optimal results. 描画呼び出し自体はリソースを集中的に使用するため、必要な作業全体を減らすことができます。Since draw calls themselves are resource-intensive, reducing them will reduce overall work required. さらに、描画呼び出し間の状態変更には、グラフィックスドライバーでのコストの高い検証と変換の手順が必要です。したがって、状態の変化を制限するためにアプリケーションの描画呼び出しを再構築する必要があります (つまり、Further, state changes between draw calls requires costly validation and translation steps in the graphics driver and thus, restructuring of your application's draw calls to limit state changes(i.e さまざまな素材など) によってパフォーマンスが向上します。different materials, etc) can boost performance.

Unity には、概要を説明し、そのプラットフォームの描画呼び出しをバッチ処理するためのダイブがあります。Unity has a great article that gives an overview and dives into batching draw calls for their platform.

シングルパスインスタンスレンダリングSingle pass instanced rendering

Unity での単一パスのインスタンスレンダリングでは、各視点の描画呼び出しを1つのインスタンス化描画呼び出しに減らすことができます。Single Pass Instanced Rendering in Unity allows for draw calls for each eye to be reduced down to one instanced draw call. 2つの描画呼び出しの間のキャッシュの一貫性により、GPU にもパフォーマンスが向上しています。Due to cache coherency between two draw calls, there is also some performance improvement on the GPU as well.

Unity プロジェクトでこの機能を有効にするにはTo enable this feature in your Unity Project

  1. プレーヤーの XR の設定を開く ([プロジェクト設定 > の編集 > ] にアクセスして、プレーヤー > XR 設定を編集)Open Player XR Settings (go to Edit > Project Settings > Player > XR Settings)
  2. [ステレオレンダリングメソッド] ドロップダウンメニューから [シングルパスインスタンス] を選択します ([Virtual Reality がサポートされる] チェックボックスをオンにする必要があります)Select Single Pass Instanced from the Stereo Rendering Method drop-down menu (Virtual Reality Supported checkbox must be checked)

この表示方法の詳細については、Unity から次の記事をお読みください。Read the following articles from Unity for details with this rendering approach.

注意

単一パスのインスタンス化に関する一般的な問題の1つは、開発者が既にインスタンス化用に作成されていない既存のカスタムシェーダーを持っている場合です。One common issue with Single Pass Instanced Rendering occurs if developers already have existing custom shaders not written for instancing. この機能を有効にした後、開発者は、一部のオブジェクトが1つの目にしか表示されないことに気付く場合があります。After enabling this feature, developers may notice some GameObjects only render in one eye. これは、関連付けられたカスタムシェーダーに、インスタンス化するための適切なプロパティがないためです。This is because the associated custom shaders do not have the appropriate properties for instancing.

この問題への対処方法については、Unityの HoloLens のシングルパスステレオレンダリングに関する説明を参照してください。See Single Pass Stereo Rendering for HoloLens from Unity for how to address this problem

静的バッチ処理Static batching

Unity では、多くの静的オブジェクトをバッチ処理して、GPU への描画呼び出しを減らすことができます。Unity is able to batch many static objects to reduce draw calls to the GPU. 静的バッチ処理は、Unity では 、1) 同じ素材を共有し、 2) すべてが静的としてマークされている (unity のオブジェクトを選択し、インスペクターの右上のチェックボックスをクリックする) ため、ほとんどのレンダラーオブジェクトで動作します)。Static Batching works for most Renderer objects in Unity that 1) share the same material and 2) are all marked as Static (Select an object in Unity and click the checkbox in the top right of the inspector). Staticとマークされたユーザーオブジェクトは、アプリケーションのランタイム全体で移動できません。GameObjects marked as Static cannot be moved throughout your application's runtime. そのため、事実上、すべてのオブジェクトの配置、移動、スケーリングなどを必要とする HoloLens では、静的バッチ処理を利用することが困難になります。イマーシブヘッドセットの場合、静的なバッチ処理によって描画呼び出しが大幅に減少し、パフォーマンスが向上します。Thus, static batching can be difficult to leverage on HoloLens where virtually every object needs to be placed, moved, scaled, etc. For immersive headsets, static batching can dramatically reduce draw calls and thus improve performance.

詳細については、「 Unity での描画呼び出しのバッチ処理」の「静的バッチ」を参照してください。Read Static Batching under Draw Call Batching in Unity for more details.

動的バッチ処理Dynamic batching

HoloLens 開発ではオブジェクトを静的としてマークするのは問題なので、動的バッチ処理は、このような機能がないことを補うために優れたツールとなります。Since it is problematic to mark objects as Static for HoloLens development, dynamic batching can be a great tool to compensate for this lacking feature. もちろん、イマーシブヘッドセットにも役立つことがあります。Of course, it is can also be useful on immersive headsets as well. Unity で動的バッチ処理を有効にすることは困難ですが、このようなオブジェクトは、を使用する必要があります) 同じ素材を共有し、 b) 他の条件の長いリストを満たすことができます。Dynamic batching in Unity can be difficult though to enable because GameObjects must a) share the same Material and b) meet a long list of other criteria.

完全な一覧については、「 Unity での描画呼び出しのバッチ処理」の動的バッチ処理を参照してください。Read Dynamic Batching under Draw Call Batching in Unity for the full list. 一般に、関連するメッシュデータは300の頂点を超えることができないため、多くの場合、このようなオブジェクトは、動的にバッチ処理されるように無効になります。Most commonly, GameObjects become invalid to be batched dynamically because the associated mesh data can be no more than 300 vertices.

その他の方法Other techniques

バッチ処理は、複数のオブジェクトが同じ素材を共有できる場合にのみ発生します。Batching can only occur if multiple GameObjects are able to share the same material. 通常、これはブロックされます。これは、作成オブジェクトがそれぞれのマテリアルに対して一意のテクスチャを持つ必要があるためです。Typically this will be blocked by the need for GameObjects to have a unique texture for their respective Material. テクスチャを1つの大きなテクスチャ (テクスチャの atlasing 呼ばれるメソッド) にまとめるのが一般的です。It is common to combine Textures into one big Texture, a method known as Texture Atlasing.

さらに、一般に、可能であれば、メッシュを1つのオブジェクトに結合することをお勧めします。Further, it is generally preferable to combine meshes into one GameObject where possible and reasonable. Unity の各レンダラーには、関連付けられた描画呼び出しと、1つのレンダラーの下で結合メッシュが送信されます。Each Renderer in Unity will have it's associated draw call(s) versus submitting a combined mesh under one Renderer.

注意

実行時にレンダラーのプロパティを変更すると、マテリアルのコピーが作成されるため、バッチ処理が中断される可能性があります。Modifying properties of Renderer.material at runtime will create a copy of the Material and thus potentially break batching. オブジェクト間で共有マテリアルのプロパティを変更するには、Renderer を使用します。Use Renderer.sharedMaterial to modify shared material properties across GameObjects.

GPU のパフォーマンスに関する推奨事項GPU performance recommendations

Unity でのグラフィックスレンダリングの最適化についての詳細情報Learn more about optimizing graphics rendering in Unity

深度バッファーの共有を最適化するOptimize depth buffer sharing

通常は、プレーヤーの XR 設定深度バッファーの共有を有効にして、ホログラムの安定性を最適化することをお勧めします。It is generally recommended to enable Depth buffer sharing under Player XR Settings to optimize for hologram stability. ただし、この設定で深さベースの遅延段階の再プロジェクションを有効にする場合は、 24 ビットの深度形式ではなく、 16 ビットの深さ形式を選択することをお勧めします。When enabling depth-based late-stage reprojection with this setting however, it is recommended to select 16-bit depth format instead of 24-bit depth format. 16ビットの深度バッファーによって、深度バッファートラフィックに関連付けられた帯域幅 (および電力) が大幅に減少します。The 16-bit depth buffers will drastically reduces the bandwidth (and thus power) associated with depth buffer traffic. これは、大きな威力を得ることができますが、 z 戦いが24ビットより16ビットで発生する可能性が高いので、わずかな深度範囲の経験にのみ適用されます。This can be a big power win, but is only applicable for experiences with a small depth range as z-fighting is more likely to occur with 16-bit than 24-bit. これらの成果物を回避するには、 Unity カメラの近距離/遠クリッププレーンを変更して、精度を低くします。To avoid these artifacts, modify the near/far clip planes of the Unity camera to account for the lower precision. HoloLens ベースのアプリケーションでは、Unity の既定の1000m ではなく、50m の遠くのクリッププレーンによって、一般に z 戦いを排除できます。For HoloLens-based applications, a far clip plane of 50m instead of the Unity default 1000m can generally eliminate any z-fighting.

全画面表示の効果を避けるAvoid full-screen effects

全画面で動作する手法は、すべてのフレームに対して数百万の操作が行われるため、非常にコストが高くなる可能性があります。Techniques that operate on the full screen can be quite expensive since their order of magnitude is millions of operations every frame. したがって、アンチエイリアシング、ブルームなどの処理後の効果を避けることをお勧めします。Thus, it is recommended to avoid post-processing effects such as anti-aliasing, bloom, and more.

最適な光源設定Optimal lighting settings

Unity でリアルタイムのグローバルな照明を使用すると、視覚的な結果を得ることができますが、非常にコストのかかる照明計算が含まれます。Real-time Global Illumination in Unity can provide oustanding visual results but involves quite expensive lighting calculations. ウィンドウ > レンダリングの光源の設定を使用して Unity シーンファイルごとにリアルタイムのグローバル照明を無効にして、リアルタイムのグローバル照明をオフにすることをお勧め >。 > It is recommended to disable Realtime Global Illumination for every Unity scene file via Window > Rendering > Lighting Settings > Uncheck Real-time Global Illumination.

さらに、すべてのシャドウキャストを無効にすることをお勧めします。これにより、Unity シーンに負荷の高い GPU パスも追加されます。Further, it is recommended to disable all shadow casting as these also add expensive GPU passes onto a Unity scene. 影はライトごとに無効にすることができますが、品質設定を使用して総合的を制御することもできます。Shadows can be disable per light but can also be controlled holistically via Quality settings.

> プロジェクト設定を編集し、[品質] カテゴリを選択して、UWP プラットフォームの [低品質] を選択 > ます。Edit > Project Settings, then select the Quality category > Select Low Quality for the UWP Platform. また、 shadowsプロパティを設定して、影を無効にすることもできます。One can also just set the Shadows property to Disable Shadows.

Poly 数を減らすReduce poly count

通常、Polygon カウントはPolygon count is usually reduced by either

  1. シーンからのオブジェクトの削除Removing objects from a scene
  2. 指定されたメッシュの多角形の数を減らす資産の決定Asset decimation which reduces the number of polygons for a given mesh
  3. アプリケーションに詳細レベル (LOD) システムを実装して、同じ geometry の低いポリゴンバージョンで遠く離れたオブジェクトをレンダリングするImplementing a Level of Detail (LOD) System into your application which renders far away objects with lower-polygon version of the same geometry

Unity のシェーダーについてUnderstanding shaders in Unity

シェーダーをパフォーマンスで比較するための簡単な方法は、実行時に各操作が実行される平均操作数を特定することです。An easy approximation to compare shaders in performance is to identify the average number of operations each executes at runtime. これは、Unity で簡単に実行できます。This can be done easily in Unity.

  1. シェーダー資産を選択するか、素材を選択します。次に、[インスペクター] ウィンドウの右上隅にある歯車アイコンを選択し、[シェーダーの選択] をクリックします。Select your shader asset or select a material, then in top right corner of the inspector window, select the gear icon and then "Select Shader"

    Unity でシェーダーを選択する

  2. シェーダー資産を選択した状態で、[インスペクター] ウィンドウの下にある [コードのコンパイルと表示] ボタンをクリックします。With the shader asset selected, click the "Compile and show code" button under the inspector window

    Unity でシェーダーコードをコンパイルする

  3. コンパイル後、頂点シェーダーとピクセルシェーダーの両方の異なる操作の数を使用して、結果の統計セクションを探します (注: ピクセルシェーダーはフラグメントシェーダーとも呼ばれます)。After compiling, look for the statistics section in the results with the number of different operations for both the vertex and pixel shader (Note: pixel shaders are often also called fragment shaders)

    Unity の標準シェーダー操作

ピクセルシェーダーの最適化Optmize pixel shaders

上記のメソッドを使用してコンパイルされた統計結果を確認すると、通常、フラグメントシェーダー頂点シェーダーよりも多くの操作を平均で実行します。Looking at the compiled statistic results using the method above, the fragment shader will generally execute more operations than the vertex shader on average. フラグメントシェーダーは、ピクセルシェーダーとも呼ばれ、画面出力のピクセルごとに実行されます。一方、頂点シェーダーは、画面に描画されるすべてのメッシュの頂点ごとに実行されます。The fragment shader, also known as the pixel shader, is executed per pixel on the screen output while the vertex shader is only executed per-vertex of all meshes being drawn to the screen.

したがって、すべての光源の計算のために、頂点シェーダーよりも多くの命令を持つフラグメントシェーダーだけでなく、ほとんどの場合、フラグメントシェーダーは大規模なデータセットで実行されます。Thus, not only do fragment shaders have more instructions than vertex shaders because of all the lighting calculations, fragment shaders are almost always executed on a larger dataset. たとえば、画面出力が 2k x 2k のイメージの場合、フラグメントシェーダーは 2000 * 2000 = 400万回実行されます。For example, if the screen output is a 2k by 2k image, then the fragment shader can get executed 2,000*2,000 = 4,000,000 times. 2つの画面が表示される場合、2つの画面があるため、この数は2倍になります。If rendering two eyes, this number doubles since there are two screens. 混合の現実アプリケーションに複数のパス、全画面の処理後の影響、または複数のメッシュを同じピクセルにレンダリングする場合は、この数が大幅に増加します。If a mixed reality application has multiple passes, full-screen post-processing effects, or rendering multiple meshes to the same pixel, this number will increase dramatically.

そのため、フラグメントシェーダー内の操作の数を減らすと、通常、頂点シェーダーの最適化よりもはるかに高いパフォーマンスが得られます。Therefore, reducing the number of operations in the fragment shader can generally give far greater performance gains over optimizations in the vertex shader.

Unity 標準シェーダーの代替手段Unity Standard shader alternatives

物理的ベースのレンダリング (.PBR) やその他の高品質シェーダーを使用する代わりに、より高性能で安価なシェーダーを利用することを検討してください。Instead of using a physically based rendering (PBR) or other high-quality shader, look at utilizing a more performant and cheaper shader. Mixed Reality Toolkitには、mixed reality プロジェクト用に最適化されたmrtk standard shaderが用意されています。The Mixed Reality Toolkit provides the MRTK standard shader that has been optimized for mixed reality projects.

Unity では、Unity 標準シェーダーと比較して、unlit、頂点の lit、拡散、およびその他の単純化されたシェーダーオプションも提供されます。Unity also provides an unlit, vertex lit, diffuse, and other simplified shader options that are significantly faster compared to the Unity Standard shader. 詳細については、「組み込みシェーダーの使用状況とパフォーマンス」を参照してください。See Usage and Performance of Built-in Shaders for more detailed information.

シェーダーのプリロードShader preloading

シェーダーの読み込み時間を最適化するには、シェーダーのプリロードやその他のテクニックを使用します。Use Shader preloading and other tricks to optimize shader load time. 特に、シェーダーのプリロードは、ランタイムシェーダーのコンパイルによって hitches が表示されないことを意味します。In particular, shader preloading means you won't see any hitches due to runtime shader compilation.

オーバードローを制限するLimit overdraw

Unity では、シーンビューの左上隅にある [描画モード] メニューを切り替えて、[オーバードロー] を選択すると、シーンのオーバードローを表示できます。In Unity, one can display overdraw for their scene, by toggling the draw mode menu in the top left corner of the Scene view and selecting Overdraw.

一般に、GPU に送信される前にオブジェクトを事前にカリングすることで、オーバードローを軽減できます。Generally, overdraw can be mitigated by culling objects ahead of time before they are sent to the GPU. Unity は、エンジンに対して遮蔽カリングを実装する方法について詳しく説明します。Unity provides details on implementing Occlusion Culling for their engine.

メモリに関する推奨事項Memory recommendations

過剰なメモリ割り当て & 解放操作によって holographic アプリケーションに悪影響を及ぼす可能性があるため、パフォーマンスが低下したり、フレームが固定されたり、その他の有害な動作が発生したりする可能性があります。Excessive memory allocation & deallocation operations can have adverse effects on your holographic application resulting in inconsistent performance, frozen frames, and other detrimental behavior. メモリ管理はガベージコレクターによって制御されるため、Unity で開発するときは、メモリに関する考慮事項を理解することが特に重要です。It is especially important to understand memory considerations when developing in Unity since memory management is controlled by the garbage collector.

ガベージコレクションGarbage collection

Holographic アプリは、GC がアクティブ化され、実行中にスコープ外になったオブジェクトを分析し、そのメモリを解放して再利用できるようにする必要がある場合、ガベージコレクター (GC) への処理時間が緩やかになります。Holographic apps will loose processing compute time to the garbage collector (GC) when the GC is activated to analyze objects that are no longer in scope during execution and their memory needs to be released so it can be made available for re-use. 通常、一定の割り当てと割り当て解除では、ガベージコレクターの実行頻度を高くする必要があります。その結果、低下のパフォーマンスとユーザーエクスペリエンスが向上します。Constant allocations and de-allocations will generally require the garbage collector to run more frequently thus hurting performance and user experience.

Unity では、ガベージコレクターのしくみを詳しく説明する優れたページと、メモリ管理に関してより効率的なコードを記述するためのヒントが提供されています。Unity has provided an excellent page that explains in detail how the garbage collector works and tips to write more efficient code in regards to memory management.

ガベージコレクションが過剰になる最も一般的な方法の1つは、Unity 開発のコンポーネントおよびクラスへの参照をキャッシュしないことです。One of the most common practices that leads to excessive garbage collection is not caching references to components and classes in Unity development. すべての参照は、Start () または起動中 () にキャプチャし、Update () や Behaviour () などの後の関数で再利用する必要があります。Any references should be captured during Start() or Awake() and re-used in later functions such as Update() or LateUpdate().

その他のクイックヒント:Other quick tips:

  • StringBuilder C#クラスを使用して、実行時に複雑な文字列を動的に構築するUse the StringBuilder C# class to dynamically build complex strings at runtime
  • アプリケーションのすべてのビルドバージョンでまだ実行されているため、必要がなくなったときに、デバッグログ () への呼び出しを削除します。Remove calls to Debug.Log() when no longer needed as they still execute in all build versions of an app
  • Holographic アプリで一般的に多くのメモリが必要な場合は、読み込み中または移行画面を表示するときなど、読み込みフェーズ中に、 System. GC () を呼び出すことを検討してください。If your holographic app generally requires lots of memory, consider calling System.GC.Collect() during loading phases such as when presenting a loading or transition screen

オブジェクトプールObject pooling

オブジェクトプールは、オブジェクトの割り当て解除 & の継続的な割り当てのコストを削減するための一般的な手法です。Object pooling is a popular technique to reduce the cost of continuous allocations & deallocations of objects. これを行うには、同一のオブジェクトの大規模なプールを割り当て、時間の経過と共にオブジェクトを絶えず破棄するのではなく、このプールから使用可能な非アクティブなインスタンスを再利用します。This is done by allocating a large pool of identical objects and re-using inactive, available instances from this pool instead of constantly spawning and destroying objects over time. オブジェクトプールは、アプリの有効期間が可変の再使用可能なコンポーネントに最適です。Object pools are great for re-useable components that have variable lifetime during an app.

起動時のパフォーマンスStartup performance

より小さなシーンでアプリを起動し、 SceneManager を使用してシーンの残りの部分を読み込むことを検討してください。You should consider starting your app with a smaller scene, then using SceneManager.LoadSceneAsync to load the rest of the scene. これにより、アプリは可能な限り高速に対話型状態になることができます。This allows your app to get to an interactive state as fast as possible. 新しいシーンをアクティブ化し、レンダリングされたコンテンツが途切れたり順調したりする可能性がある場合は、CPU のスパイクが大きくなる可能性があることに注意してください。Be aware that there may be a large CPU spike while the new scene is being activated and that any rendered content might stutter or hitch. この問題を回避する方法の1つとして、読み込まれるシーンで allowSceneActivation プロパティを false に設定し、シーンが読み込まれるまで待機します。次に、画面を黒にオフにし、AsyncOperation を true に設定してシーンのアクティブ化を完了します。One way to work around this is to set the AsyncOperation.allowSceneActivation property to false on the scene being loaded, wait for the scene to load, clear the screen to black, and then set back to true to complete the scene activation.

スタートアップシーンが読み込まれている間、holographic スプラッシュ画面がユーザーに表示されることに注意してください。Remember that while the startup scene is loading the holographic splash screen will be displayed to the user.

関連項目See also