Unity Draw Text on Plane
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical back up.
Functioning recommendations for Unity
This commodity builds on the performance recommendations for mixed reality, but focuses on Unity-specific improvements.
We recently released an application chosen Quality Fundamentals that covers common performance, design, and environment issues and solutions for HoloLens 2 apps. This app is a neat visual demo for the content that follows.
Use recommended Unity project settings
The nigh of import commencement step when optimizing performance of mixed reality apps in Unity is to exist sure y'all're using the recommended environs settings for Unity. That article contains content with some of the most important scene configurations for building performant Mixed Reality apps. Some of these recommended settings are highlighted below, as well.
How to contour with Unity
Unity provides the Unity Profiler congenital-in, which is a neat resource to gather valuable functioning insights for your item app. Although you can run the profiler in-editor, these metrics don't stand for the true runtime environment so results should exist used cautiously. We recommend that you remotely profile your application while running on-device for the nearly accurate and actionable insights.
Unity provides bully documentation for:
- How to connect the Unity profiler to UWP applications remotely
- How to effectively diagnose performance issues with the Unity Profiler
GPU profiling
Unity profiler
With the Unity Profiler connected and afterward adding the GPU profiler (see Add Profiler in top right corner), 1 tin meet how much time is being spent on the CPU & GPU respectively in the middle of the profiler. This allows the programmer to get a quick approximation if their application is CPU or GPU bounded.
Annotation
To use GPU profiling, you demand to disable Graphics Jobs in the Unity Actor Settings. Meet Unity'southward GPU Usage Profiler module for more than details.
Unity frame debugger
Unity'southward Frame Debugger is also a powerful and insightful tool to use. It volition give you a skilful overview of what the GPU is doing each frame. Things to look out for are boosted rendering targets and blit commands to copy between them every bit these are very expensive on HoloLens. Ideally, no off-screen render targets should be used on HoloLens. These are usually added when enabling expensive rendering features (for example MSAA, HDR or total-screen furnishings like bloom) which should exist avoided.
HoloLens frame charge per unit overlay
The Device Portal System Functioning page has a skillful summary of CPU and GPU functioning of the device. You can enable Display frame rate counter in headset and Brandish frame rate graph in headset. These options will enable an FPS counter and graph, respectively, that will give y'all immediate feedback in whatsoever running awarding on your device.
PIX
PIX can be used to profile Unity applications besides. There are also detailed instructions on how to utilise and install PIX for HoloLens two. In a development build, the same scopes that y'all see in Unity's Frame Debugger will be shown in PIX besides and can exist inspected and profiled in more detail.
Note
Unity provides the ability to easily modify the render target resolution of your application at runtime through the XRSettings.renderViewportScale holding. The final image presented on-device has a fixed resolution. The platform will sample the lower resolution output to build a higher resolution prototype for rendering on displays.
UnityEngine.XR.XRSettings.renderViewportScale = 0.7f; CPU performance recommendations
The content below covers more than in-depth performance practices, especially targeted for Unity & C# development.
Cache references
Nosotros recommend caching references to all relevant components and GameObjects at initialization because repeating function calls such every bit GetComponent<T>() and Photographic camera.main are more expensive relative to the memory cost to store a pointer. . Camera.master just uses FindGameObjectsWithTag() underneath, which expensively searches your scene graph for a photographic camera object with the "MainCamera" tag.
using UnityEngine; using System.Collections; public class ExampleClass : MonoBehaviour { private Camera cam; private CustomComponent comp; void Start() { cam = Photographic camera.main; comp = GetComponent<CustomComponent>(); } void Update() { // Good this.transform.position = cam.transform.position + cam.transform.forward * 10.0f; // Bad this.transform.position = Camera.master.transform.position + Photographic camera.main.transform.forwards * 10.0f; // Expert comp.DoSomethingAwesome(); // Bad GetComponent<CustomComponent>().DoSomethingAwesome(); } } Note
Avoid GetComponent(string)
When using GetComponent(), there are a scattering of different overloads. It is important to always employ the Type-based implementations and never the string-based searching overload. Searching by string in your scene is significantly more costly than searching past Type.
(Adept) Component GetComponent(Type blazon)
(Good) T GetComponent<T>()
(Bad) Component GetComponent(string)>
Avoid expensive operations
-
Avoid use of LINQ
Although LINQ tin be clean and easy to read and write, it more often than not requires more ciphering and retentivity than if you lot wrote the algorithm manually.
// Example Lawmaking using System.Linq; List<int> information = new Listing<int>(); data.Whatsoever(x => x > 10); var outcome = from ten in data where x > 10 select ten; -
Common Unity APIs
Certain Unity APIs, although useful, tin exist expensive to execute. Most of these involve searching your entire scene graph for some matching listing of GameObjects. These operations can generally be avoided past caching references or implementing a manager component for the GameObjects to runway 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()
Note
SendMessage() and BroadcastMessage() should exist eliminated at all costs. These functions can be on the order of 1000x slower than direct office calls.
-
Beware of boxing
Boxing is a core concept of the C# language and runtime. Information technology'due south the process of wrapping value-typed variables such as
char,int,bool, etc. into reference-typed variables. When a value-typed variable is "boxed", information technology's wrapped in aOrganization.Object, which is stored on the managed heap. Retention is allocated and somewhen when disposed must exist processed by the garbage collector. These allocations and deallocations incur a performance cost and in many scenarios are unnecessary or tin can be easily replaced by a less expensive alternative.To avert boxing, exist sure that the variables, fields, and properties in which you lot store numeric types and structs (including
Nullable<T>) are strongly typed every bit specific types such asint,float?orMyStruct, instead of using object. If putting these objects into a list, exist certain to apply a strongly typed listing such asList<int>rather thanList<object>orArrayList.Example of boxing in C#
// boolean value type is boxed into object boxedMyVar on the heap bool myVar = true; object boxedMyVar = myVar;
Repeating code paths
Any repeating Unity callback functions (i.e Update) that are executed many times per 2d and/or frame should exist written carefully. Any expensive operations hither volition have huge and consequent affect on performance.
-
Empty callback functions
Although the code below may seem innocent to get out in your awarding, peculiarly since every Unity script auto-initializes with an Update method, these empty callbacks tin can become expensive. Unity operates back and forth between an unmanaged and managed code boundary, betwixt UnityEngine code and your application code. Context switching over this bridge is fairly expensive, even if at that place's nil to execute. This becomes especially problematic if your app has 100s of GameObjects with components that have empty repeating Unity callbacks.
void Update() { }
Note
Update() is the most mutual manifestation of this performance issue simply other repeating Unity callbacks, such as the following can be equally as bad, if not worse: FixedUpdate(), LateUpdate(), OnPostRender", OnPreRender(), OnRenderImage(), etc.
-
Operations to favor running one time per frame
The following Unity APIs are common operations for many Holographic Apps. Although non always possible, the results from these functions can commonly be computed in one case and the results reutilized across the application for a given frame.
a) It's skilful do to have a dedicated Singleton class or service to handle your gaze Raycast into the scene and then reuse this result in all other scene components, instead of making repeated and identical Raycast operations past each component. Some applications may require raycasts from unlike origins or confronting different LayerMasks.
UnityEngine.Physics.Raycast() UnityEngine.Physics.RaycastAll()b) Avert GetComponent() operations in repeated Unity callbacks like Update() by caching references in Start() or Awake()
UnityEngine.Object.GetComponent()c) Information technology's proficient practice to instantiate all objects, if possible, at initialization and use object pooling to recycle and reuse GameObjects throughout runtime of your application
UnityEngine.Object.Instantiate() -
Avoid interfaces and virtual constructs
Invoking function calls through interfaces vs directly objects or calling virtual functions can ofttimes be much more expensive than using straight constructs or direct part calls. If the virtual function or interface is unnecessary, and then information technology should exist removed. All the same, the performance striking for these approaches is worth the merchandise-off if using them simplifies evolution collaboration, lawmaking readability, and code maintainability.
Mostly, the recommendation is to non mark fields and functions equally virtual unless there's a clear expectation that this fellow member needs to be overwritten. One should be especially conscientious around high-frequency code paths that are called many times per frame or fifty-fifty once per frame such equally an
UpdateUI()method. -
Avert passing structs past value
Different classes, structs are value-types and when passed straight to a function, their contents are copied into a newly created instance. This re-create adds CPU cost, too as additional memory on the stack. For minor structs, the consequence is minimal and thus acceptable. Withal, for functions repeatedly invoked every frame every bit well as functions taking large structs, if possible modify the function definition to pass by reference. Larn more here
Miscellaneous
-
Physics
a) Generally, the easiest way to improve physics is to limit the amount of time spent on Physics or the number of iterations per second. This volition reduce simulation accuracy. Run across TimeManager in Unity
b) The types of colliders in Unity have widely different performance characteristics. The guild below lists the most performant colliders to to the lowest degree performant colliders from left to correct. It's important to avoid Mesh Colliders, which are substantially more expensive than the primitive colliders.
Sphere < Capsule < Box <<< Mesh (Convex) < Mesh (non-Convex)
Meet Unity Physics Best Practices for more info
-
Animations
Disable idle animations by disabling the Animator component (disabling the game object won't have the aforementioned effect). Avert blueprint patterns where an animator sits in a loop setting a value to the same affair. In that location'southward considerable overhead for this technique, with no upshot on the awarding. Learn more here.
-
Complex algorithms
If your awarding is using complex algorithms such equally inverse kinematics, path finding, etc, look to find a simpler approach or adjust relevant settings for their operation
CPU-to-GPU performance recommendations
Generally, CPU-to-GPU performance comes down to the draw calls submitted to the graphics card. To ameliorate 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. Farther, land changes between describe calls require costly validation and translation steps in the graphics driver and thus, restructuring of your awarding's describe calls to limit state changes (i.e different materials, etc) tin heave performance.
Unity has a great article that gives an overview and dives into batching draw calls for their platform.
- Unity Draw Call Batching
Single pass instanced rendering
Single Pass Instanced Rendering in Unity allows for draw calls for each center to be reduced downwards to one instanced draw call. Considering of cache coherency betwixt two draw calls, in that location's also some performance comeback on the GPU likewise.
To enable this characteristic in your Unity Project
- Open Thespian XR Settings (go to Edit > Project Settings > Role player > XR Settings)
- Select Single Pass Instanced from the Stereo Rendering Method drop-down bill of fare (Virtual Reality Supported checkbox must be checked)
Read the following articles from Unity for details with this rendering approach.
- How to maximize AR and VR performance with advanced stereo rendering
- Single Pass Instancing
Note
One common issue with Unmarried Pass Instanced Rendering occurs if developers already have existing custom shaders not written for instancing. After enabling this feature, developers may detect some GameObjects only render in one eye. This is because the associated custom shaders practise non accept the appropriate properties for instancing.
Run across Single Pass Stereo Rendering for HoloLens from Unity for how to accost this problem
Static batching
Unity is able to batch many static objects to reduce draw calls to the GPU. Static Batching works for about Renderer objects in Unity that ane) share the aforementioned cloth and ii) are all marked as Static (Select an object in Unity and select the checkbox in the top right of the inspector). GameObjects marked every bit Static cannot exist moved throughout your awarding's runtime. Thus, static batching tin 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 describe calls and thus improve operation.
Read Static Batching nether Draw Call Batching in Unity for more than details.
Dynamic batching
Since information technology'due south problematic to marker objects as Static for HoloLens development, dynamic batching can exist a great tool to compensate for this lacking feature. It tin as well exist useful on immersive headsets, also. However, dynamic batching in Unity tin exist difficult to enable considering GameObjects must a) share the same Material and b) meet a long listing of other criteria.
Read Dynamic Batching under Draw Call Batching in Unity for the full list. Most commonly, GameObjects get invalid to be batched dynamically, because the associated mesh information 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. It'south common to combine Textures into one big Texture, a method known as Texture Atlasing.
Furthermore, it's preferable to combine meshes into one GameObject where possible and reasonable. Each Renderer in Unity volition take its associated draw call(s) versus submitting a combined mesh nether one Renderer.
Annotation
Modifying properties of Renderer.material at runtime will create a copy of the Cloth and thus potentially suspension batching. Utilise Renderer.sharedMaterial to change shared material properties across GameObjects.
GPU functioning recommendations
Acquire more well-nigh optimizing graphics rendering in Unity
Bandwidth and make full rates
When rendering a frame on the GPU, an application is either bound by retention bandwidth or fill rate.
- Memory bandwidth is the rate of reads and writes the GPU tin can do from retention
- In Unity, alter Texture Quality in Edit > Projection Settings > Quality Settings.
- Fill rate refers to the pixels that can be drawn per 2nd by the GPU.
- In Unity, use the XRSettings.renderViewportScale property.
Optimize depth buffer sharing
It'southward recommended to enable Depth buffer sharing under Player XR Settings to optimize for hologram stability. When enabling depth-based late-stage reprojection with this setting however, information technology's recommended to select 16-scrap depth format instead of 24-bit depth format. The sixteen-bit depth buffers volition drastically reduce the bandwidth (and thus power) associated with depth buffer traffic. This tin can be a large win both in power reduction and performance improvement. However, there are two possible negative outcomes by using 16-bit depth format.
Z-Fighting
The reduced depth range allegiance makes z-fighting more than likely to occur with 16 bit than 24-bit. To avoid these artifacts, modify the near/far clip planes of the Unity camera to account for the lower precision. For HoloLens-based applications, a far clip plane of 50 m instead of the Unity default 1000 yard can more often than not eliminate any z-fighting.
Disabled Stencil Buffer
When Unity creates a Return Texture with sixteen-flake depth, there'southward no stencil buffer created. Selecting 24-chip depth format, per Unity documentation, will create a 24-scrap z-buffer, every bit well every bit an [8-chip stencil buffer] (https://docs.unity3d.com/Transmission/SL-Stencil.html) (if 32-bit is applicable on a device, which is generally the instance such as HoloLens).
Avoid full-screen effects
Techniques that operate on the full screen can exist expensive since their order of magnitude is millions of operations every frame. It's recommended to avoid mail service-processing effects such as anti-aliasing, bloom, and more.
Optimal lighting settings
Real-time Global Illumination in Unity can provide outstanding visual results but involves expensive lighting calculations. We recommended disabling real-time Global Illumination for every Unity scene file via Window > Rendering > Lighting Settings > Uncheck Real-time Global Illumination.
Furthermore, it'southward recommended to disable all shadow casting equally these likewise add expensive GPU passes onto a Unity scene. Shadows can be disable per light just can also be controlled holistically via Quality settings.
Edit > Project Settings, then select the Quality category > Select Depression Quality for the UWP Platform. I tin can also just gear up the Shadows belongings to Disable Shadows.
Nosotros recommended that you use broiled lighting with your models in Unity.
Reduce poly count
Polygon count is reduced by either
- Removing objects from a scene
- Nugget decimation, which reduces the number of polygons for a given mesh
- Implementing a Level of Item (LOD) Arrangement into your awarding, which renders far away objects with lower-polygon version of the same geometry
Understanding shaders in Unity
An easy approximation to compare shaders in operation is to identify the average number of operations each executes at runtime. This tin exist done easily in Unity.
-
Select your shader nugget or select a material, and then in the top-correct corner of the inspector window, select the gear icon followed by "Select Shader"
-
With the shader asset selected, select the "Compile and show code" button under the inspector window
-
After compiling, look for the statistics section in the results with the number of dissimilar operations for both the vertex and pixel shader (Note: pixel shaders are oftentimes besides called fragment shaders)
Optimize 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, likewise 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 accept more instructions than vertex shaders because of all the lighting calculations, fragment shaders are almost e'er executed on a larger dataset. For example, if the screen output is a 2k past 2k image, so the fragment shader tin can get executed 2,000*2,000 = four,000,000 times. If rendering ii eyes, this number doubles since at that place are ii screens. If a mixed reality application has multiple passes, full-screen post-processing furnishings, 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 requite far greater performance gains over optimizations in the vertex shader.
Unity Standard shader alternatives
Instead of using a physically based rendering (PBR) or another high-quality shader, wait at utilizing a more performant and cheaper shader. The Mixed Reality Toolkit provides the MRTK standard shader that has been optimized for mixed reality projects.
Unity also provides an unlit, vertex lit, diffuse, and other simplified shader options that are faster compared to the Unity Standard shader. See Usage and Operation of Congenital-in Shaders for more detailed data.
Shader preloading
Use Shader preloading and other tricks to optimize shader load time. In particular, shader preloading means y'all won't see whatsoever hitches due to runtime shader compilation.
Limit overdraw
In Unity, 1 can display overdraw for their scene, by toggling the draw mode menu in the top-left corner of the Scene view and selecting Overdraw.
Mostly, overdraw tin be mitigated by alternative objects alee of time before they're sent to the GPU. Unity provides details on implementing Apoplexy Culling for their engine.
Memory recommendations
Excessive memory allocation & deallocation operations tin have adverse effects on your holographic application, resulting in inconsistent performance, frozen frames, and other detrimental behavior. It'due south particularly important to understand memory considerations when developing in Unity since retentivity management is controlled by the garbage collector.
Garbage collection
Holographic apps volition lose 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 exist released, so it tin be made available for reuse. Constant allocations and de-allocations volition generally crave the garbage collector to run more frequently, thus hurting operation and user experience.
Unity has provided an fantabulous page that explains in detail how the garbage collector works and tips to write more efficient code in regards to memory management.
- Optimizing garbage drove in Unity games
One of the most common practices that leads to excessive garbage collection isn't caching references to components and classes in Unity development. Any references should be captured during Start() or Awake() and reused in later functions such as Update() or LateUpdate().
Other quick tips:
- Use the StringBuilder C# class to dynamically build circuitous strings at runtime
- Remove calls to Debug.Log() when no longer needed, every bit they nevertheless execute in all build versions of an app
- If your holographic app generally requires lots of retentivity, consider calling Arrangement.GC.Collect() during loading phases such as when presenting a loading or transition screen
Object pooling
Object pooling is a popular technique for reducing the price of continuous object allocation and deallocations. This is washed past allocating a large puddle of identical objects and reusing inactive, available instances from this puddle instead of constantly spawning and destroying objects over time. Object pools are swell for reuseable components that have variable lifetime during an app.
- Object Pooling Tutorial in Unity
Startup operation
Consider starting your app with a smaller scene, and so using SceneManager.LoadSceneAsync to load the rest of the scene. This allows your app to get to an interactive state every bit fast every bit possible. There may be a large CPU fasten while the new scene is being activated and that any rendered content might stutter or hitch. I manner to piece of work around this is to gear up the AsyncOperation.allowSceneActivation property to "faux" on the scene beingness loaded, wait for the scene to load, clear the screen to black, and and so set it back to "truthful" to complete the scene activation.
Remember that while the startup scene is loading, the holographic splash screen will exist displayed to the user.
See also
- Optimizing graphics rendering in Unity games
- Optimizing garbage drove in Unity games
- Physics Best Practices [Unity]
- Optimizing Scripts [Unity]
Feedback
Submit and view feedback for
Source: https://docs.microsoft.com/en-us/windows/mixed-reality/develop/unity/performance-recommendations-for-unity
0 Response to "Unity Draw Text on Plane"
Postar um comentário