【Einheit】 Strategie zur Szenenoptimierung

Strategie zur Unity-Szenenoptimierung

GPU-Instanzierung

GPU-Instancing kann verwendet werden, um mehrere Objekte mit demselben Netz, dem gleichen Material und unterschiedlichen Materialeigenschaften in einem Stapel zusammenzuführen Reduzieren Sie die Anzahl derDraw Calls. Dies verbessert die Leistung und Rendering-Effizienz.

Mithilfe der GPU-Instanzierung können Geometrien gezeichnet werden, die in einer Szene mehrfach vorkommen, beispielsweise Bäume oder Büsche.

Render-Pipeline-Kompatibilität

Besonderheit Integrierte Rendering-Pipeline Universelle Rendering-Pipeline (URP) High Definition Rendering Pipeline (HDRP) Benutzerdefinierte programmierbare Rendering-Pipeline (SRP)
GPU-Instanzierung Ja es ist 1) es ist 1) es ist 1)

Achtung :

  1. Nur wenn der Shader nicht mit SRP Batcher kompatibel ist.

**GPU-Instanzierung einrichten**

Die Einrichtung ist einfach und erfordert nur einen Schritt

Suchen Sie unter dem Standard-Shader nach GPU-Instancing aktivieren und aktivieren Sie es.


Kontrasteffekt

Wenn nicht aktiviert: Batches beträgt etwa 230, Saved By Batching ist 0

Nach der Überprüfung: Batches ist 8, Saved By Batching ist etwa 222

Nachdem Sie den folgenden Shader verwendet haben, um dem Material zufällige Farben hinzuzufügen: „Batches“ beträgt 4, „Saved By Batching“ beträgt 63 (es werden weniger Batches vorhanden sein, wenn hier kein Schatten hinzugefügt wird).

Auffüllen:

MaterialPropertyBlock

Die Stapelverarbeitung funktioniert grundsätzlich mit dem gleichen Material. MaterialPropertyBlock kann verwendet werden, wenn eine Stapelverarbeitung von Modellen mit denselben Materialeigenschaften, aber unterschiedlichen Shader erforderlich ist.

MaterialPropertyBlock kann nicht nur in Renderer.SetPropertyBlock, sondern auch in Graphics.DrawMesh verwendet werden.

    void Start()
    {
        MaterialPropertyBlock material = new MaterialPropertyBlock();
        material.SetColor("_Color", new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f)));
        GetComponent<MeshRenderer>().SetPropertyBlock(material);

    }

Hier können Sie feststellen, dass die Farben zwar unterschiedlich sind, der Shader jedoch auf dasselbe verweist

**Shader erstellen, die GPU-Instanzierung unterstützen**

Render-Pipeline-Kompatibilität

Besonderheit Integrierte Rendering-Pipeline Universelle Rendering-Pipeline (URP) High Definition Rendering Pipeline (HDRP) Benutzerdefinierte programmierbare Rendering-Pipeline (SRP)
Benutzerdefinierter GPU-Instanz-Shader Ja NEIN NEIN NEIN

Beispiele für Vertex- und Fragment-Shader

Shader "Custom/SimplestInstancedShader"
{
    
    
    Properties
    {
    
    
        _Color ("Color", Color) = (1, 1, 1, 1)
    }

    SubShader
    {
    
    
        Tags {
    
     "RenderType"="Opaque" }
        LOD 100

        Pass
        {
    
    
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
           //生成实例化变体。它是可选的。
            #pragma multi_compile_instancing
            #include "UnityCG.cginc"

            struct appdata
            {
    
    
                float4 vertex : POSITION;
               //在顶点着色器输入/输出结构中定义INSTANCE_ID。
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f
            {
    
    
                float4 vertex : SV_POSITION;
                //使INSTANCE_ID访问片元着色器中的实例化属性。
                UNITY_VERTEX_INPUT_INSTANCE_ID 
            };
            //声明名为 的每个实例常量缓冲区的开始
            UNITY_INSTANCING_BUFFER_START(Props)
                UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
           //声明名为 的每个实例常量缓冲区的结尾     
            UNITY_INSTANCING_BUFFER_END(Props)

            v2f vert(appdata v)
            {
    
    
                v2f o;
				//允许顶点着色器函数访问INSTANCE_ID
                UNITY_SETUP_INSTANCE_ID(v);
                //将INSTANCE_ID从输入结构复制到顶点着色器中的输出结构。
                UNITY_TRANSFER_INSTANCE_ID(v, o);
                o.vertex = UnityObjectToClipPos(v.vertex);
                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
    
    
                //允许片元着色器函数访问INSTANCE_ID
                UNITY_SETUP_INSTANCE_ID(i);
                //访问实例化常量缓冲区中的每个实例着色器属性
                return UNITY_ACCESS_INSTANCED_PROP(Props, _Color);
            }
            ENDCG
        }
    }
}

Statische Stapelverarbeitung

Es reduziert Rendering-Aufrufe, indem mehrere statische Objekte in einem Stapel zusammengeführt werden, wodurch die Belastung von CPU und GPU verringert wird. Es kann die Anzahl der Draw-Aufrufe während des Renderns erheblich reduzieren und dadurch die Leistung verbessern.

Statische Stapelverarbeitung eignet sich für Objekte, die zur Laufzeit ihre Position, Drehung oder Skalierung nicht ändern, wie z. B. Gelände, Gebäude usw.

Render-Pipeline-Kompatibilität

Besonderheit Integrierte Rendering-Pipeline Universelle Rendering-Pipeline (URP) High Definition Rendering Pipeline (HDRP) Benutzerdefinierte programmierbare Rendering-Pipeline (SRP)
Statische Stapelverarbeitung Ja Ja Ja Ja

Statische Stapelverarbeitungseinstellungen

Auch die Einrichtung ist sehr einfach, nur zwei Schritte

  1. Überprüfen Sie dies unter ProjectSettings→player→OtherSetting→StaticBatching

  2. Suchen Sie unter dem Standard-Shader nach GPU-Instancing aktivieren und aktivieren Sie es.

Einschränkungen der statischen Stapelverarbeitung

  • Spielobjekte sind aktiv und gesperrt (nicht gesperrte Objekte werden zwangsweise gesperrt).
  • Das Spielobjekt verfügt über eine MeshFilter-Komponente und ist aktiviert.
  • Die MeshFilter-Komponente referenziert Mesh
  • Das Netz hat mehr Eckpunkte als 0.
  • Dieses Raster wurde noch nicht mit einem anderen Raster zusammengeführt.
  • Das Spielobjekt verfügt über eine MeshRenderer-Komponente und ist aktiviert.
  • Um Netze stapelweise zusammenzufügen, verwenden Sie dieselben Scheitelpunktattribute. Beispielsweise kann Unity ein Netz stapeln, das die Scheitelpunktposition, die Scheitelpunktnormale und eine UV verwendet, aber kein Netz, das die Scheitelpunktposition, die Scheitelpunktnormale, UV0, UV1 und die Scheitelpunkttangente verwendet.

Wirkung

„Batches“ ist 8, „Gespeichert durch Batch“ ist 211

Statische Stapelverarbeitungssteuerung

Verwenden Sie die Klasse StaticBatchingUtility, um die statische Stapelverarbeitung zu steuern.

using UnityEngine;

public class StaticBatchingController : MonoBehaviour
{
    void Start()
    {
       StartStaticBatch();
    }

    GameObject[] GetGameObjectsToBatch()
    {
        // 返回需要静态批处理的游戏对象数组
        // 例如:可以通过标签、层级或者其他方式来获取需要静态批处理的游戏对象
        // 这里只是一个简单示例,实际情况可能需要根据具体需求来获取游戏对象
        return GameObject.FindGameObjectsWithTag("StaticBatchingObject");
    }
    void StartStaticBatch()
    {
        // 获取所有需要静态批处理的游戏对象
        GameObject[] gameObjectsToBatch = GetGameObjectsToBatch();
        // 执行静态批处理
        StaticBatchingUtility.Combine(gameObjectsToBatch, this.gameObject);
    }
    void StopStaticBatch()
    {
        // 禁用静态批处理
        StaticBatchingUtility.Combine(null, this.gameObject);
    }
}

Dynamische Stapelverarbeitung

Reduzieren Sie die Anzahl der Renderaufrufe und verbessern Sie die Bildrate und Leistung, indem Sie zur Laufzeit mehrere statische oder dynamische Spielobjekte dynamisch zu einem Stapel zusammenführen.

Render-Pipeline-Kompatibilität

Besonderheit Integrierte Rendering-Pipeline Universelle Rendering-Pipeline (URP) High Definition Rendering Pipeline (HDRP) Benutzerdefinierte programmierbare Rendering-Pipeline (SRP)
Dynamische Stapelverarbeitung Ja Ja NEIN Ja

Statische Stapelverarbeitungseinstellungen

Auch die Einrichtung ist sehr einfach, nur ein Schritt

Überprüfen Sie dies unter ProjectSettings→player→OtherSetting→DynamicBatching

Einschränkungen der dynamischen Stapelverarbeitung

  • Unity kann keine dynamische Stapelverarbeitung auf Netze anwenden, die mehr als 225 Scheitelpunkte enthalten. Dies liegt daran, dass beim dynamischen Stapeln von Netzen ein Overhead pro Scheitelpunkt entsteht.
    Unter Verwendung von Scheitelpunktpositionen, Scheitelpunktnormalen und einem einzelnen UV kann Unity bis zu 225 Scheitelpunkte stapeln. Wenn der Shader jedoch die Scheitelpunktposition, die Scheitelpunktnormale, UV0, UV1 und die Scheitelpunkttangente verwendet, kann Unity nur 180 Scheitelpunkte stapeln.
  • Wenn Objekte unterschiedliche Materialinstanzen verwenden, kann Unity sie nicht stapeln, obwohl sie im Wesentlichen einen Shader verwenden. Die einzige Ausnahme ist das Schattenwurf-Rendering.
  • Spielobjekte mit Lightmaps verfügen über zusätzliche Renderer-Parameter. Das bedeutet, dass, wenn Sie Lightmap-Spielobjekte stapeln möchten, diese auf dieselbeLightmapPosition zeigen müssen.
  • Unity kann dynamisches Batching nicht vollständig auf Shader-Objekte anwenden, die mehrere Durchgänge verwenden.
    • Fast alle Unity-Shader unterstützen mehrere LichterVorwärtsrenderingUm dies zu erreichen, verarbeiten sie einen zusätzlichen Render-Durchgang. Unity stapelt nur den ersten Renderdurchlauf. Es ist nicht möglich, für jedes Pixellicht zusätzliche Zeichenaufrufe zu stapeln.

Wirkung

Die Anzahl der Chargen beträgt 8, die durch Stapelverarbeitung gespeicherte Anzahl beträgt etwa 220

Netze manuell zusammenführen

Das manuelle Zusammenführen mehrerer Netze zu einem Netz ist eine gute Alternative zur statischen und dynamischen Stapelverarbeitung in Situationen, in denen die Netze nahe beieinander liegen und sich nicht relativ zueinander bewegen.

Warnung: Unity kann Ihre kombinierten Netze nicht einzeln aussortieren. Das heißt, wenn ein Teil des kombinierten Netzes auf dem Bildschirm erscheint, zeichnet Unity das gesamte kombinierte Netz. Wenn die Netze statisch sind und Sie möchten, dass Unity sie einzeln aussortiert, verwenden Sie statisches Batching.

So richten Sie zusammengeführte Gitter ein

  • Im Asset-Generierungstool beim Erstellen eines Netzes. Das heißt, wenn sie während der Modellproduktionsphase zusammengeführt werden und dasselbe Modell auf diese Weise verarbeitet wird, wird das Modellvolumen größer.
  • Verwenden von Mesh.CombineMeshes in Unity

Verwendung von CombineMeshes

//强制添加组件
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class ExampleClass : MonoBehaviour
{
    void Start()
    {
        MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>();
     //  CombineInstance 结构体 用于描述要使用 Mesh.CombineMeshes 组合的网格。
        CombineInstance[] combine = new CombineInstance[meshFilters.Length];

        int i = 0;
        while (i < meshFilters.Length)
        {
            combine[i].mesh = meshFilters[i].sharedMesh;
            combine[i].transform = meshFilters[i].transform.localToWorldMatrix;
            meshFilters[i].gameObject.SetActive(false);

            i++;
        }

        Mesh mesh = new Mesh();
        mesh.CombineMeshes(combine);
        transform.GetComponent<MeshFilter>().sharedMesh = mesh;
        transform.gameObject.SetActive(true);
    }
}
CombineInstance-Feld veranschaulichen
lightmapScaleOffset Die auf das Netz angewendete UV-Skala und der Offset der gebackenen Lightmap.
Gittergewebe Die Maschen zum Kombinieren.
realtimeLightmapScaleOffset Auf das Netz angewendete UV-Skalierung und Offset der Lightmap in Echtzeit.
subMeshIndex Der Untergitterindex des Gitters.
verwandeln Die Matrix zum Transformieren des Netzes vor dem Kombinieren. Ein Beispiel finden Sie unter Mesh.CombineMeshes.

Wirkung

„Batches“ ist 8, „Gespeichert durch Batch“ ist 0

Okklusions-Culling

Ganz zu schweigen vom Okklusions-Culling

Die häufige Verwendung von Occlusion Culling kann zu Leistungsproblemen führen, insbesondere in komplexen Szenen. Denn jedes Mal, wenn sich die Kamera bewegt oder sich die Szene ändert, müssen die Occlusion-Culling-Informationen neu berechnet werden, was eine gewisse Menge an Rechenressourcen verbrauchen kann.

LOD

Wenn Sie LOD (Level of Detail) in Unity verwenden, können Sie basierend auf dem Abstand zwischen der Kamera und dem Objekt automatisch zwischen verschiedenen Modellebenen wechseln, um die Leistung zu verbessern und den Rendering-Aufwand zu reduzieren.

unityLOD-Einstellungsmethode

  1. Erstellen Sie mehrere unterschiedliche Modellebenen, um Fern-, Mittel- und Nahmodelle darzustellen.

  2. Machen Sie diese Modelle zu Kindern desselben Spielobjekts und fügen Sie LOD-Gruppenkomponenten hinzu.

  3. Legen Sie den Abstand und das entsprechende Modell jeder Ebene in der LOD-Gruppenkomponente fest.

  4. Unity wechselt automatisch zwischen verschiedenen Modellebenen basierend auf der Entfernung zwischen Kamera und Objekt.

Wirkung

Kombinierbar mit statischer Stapelverarbeitung und dynamischer Stapelverarbeitung

„Batches“ beträgt 11, „Saved By Batching“ beträgt etwa 310

Layer-Culling-LayerCullDistances

Wird verwendet, um den Ausleseabstand der Kamera beim Rendern verschiedener Ebenen anzugeben. Durch Festlegen von „layerCullDistances“ können Sie den Ausleseabstand der Kamera beim Rendern verschiedener Ebenen steuern und so die Renderleistung verbessern. Layer-Culling ist ähnlich wie lod. Es basiert ebenfalls auf der Entfernung. Der Unterschied besteht darin, dass Layer-Culling nicht ersetzt wird

float[] distances = new float[32];//设定32个默认图层
distances[11] = 300;//为第11层设定距离
Camera.mian.layerCullDistances = distances;//将剔除层传递给相机

Supongo que te gusta

Origin blog.csdn.net/dxs1990/article/details/134338121
Recomendado
Clasificación