Serie de optimización UGUI (2) ------ Concepto de representación

Esta serie es para aprender la solución general de UGUI de Siki Academy: notas de optimización (Unity 2019.1.0f2)


dirección de github: https://github.com/BlueMonk1107/UGUISolution
Dirección del algoritmo de bloque Atlas: https://github.com/DaVikingCode/UnityRuntimeSpriteSheetsGenerator
sitio web oficial de texturepacker: https://www.codeandweb.com/texturepacker Dirección de descarga
del código fuente UGUI : https://bitbucket.org/Unity-Technologies/ui/downloads/?tab=downloads


1. Representación de objetos transparentes

La representación de objetos transparentes no escribe la profundidad. La representación de objetos translúcidos de atrás hacia adelante causará el problema de sobredibujado, por lo que la interfaz de usuario se dibuja
imagen.png
en la cola transparente, por lo que la interfaz de usuario en UI Everything tiene 28 mezclas. , y todos se dibujan de atrás hacia adelante, por lo que la parte de la interfaz de usuario debe optimizarse sobre el dibujo. Al dibujar una gran cantidad de IU, excederá la capacidad de representación de la CPU del dispositivo móvil. Valor de profundidad: cuanto mayor sea la profundidad, más lejos lejos de la


cámara
imagen.png
Caso pequeño de prueba de profundidad: los objetos que usan el mismo sombreador se mostrarán en la parte delantera después de encender ZWrite

Shader "My Shader/AlphaShadera"
{
    
    
  SubShader{
    
    
        //开启深度测试
        ZWrite on 
        ZTest Always
        Pass{
    
    
        
        Color(1,1,1,1)
        }
    
    }
}

2. Lógica de ejecución de la reconstrucción de la red.

La gran mayoría de los problemas de la interfaz de usuario se reducen a problemas de reconstrucción de malla

1. Reposición

Es agrupar todos los objetos debajo del lienzo para un procesamiento unificado para generar malla.
Si algún objeto debajo del lienzo cambia, provocará una operación por lotes para volver a dibujar todos los objetos debajo del lienzo. Por lo tanto, si la interfaz de usuario de un proyecto
con consumo de alto .

2. Reconstruir

Para volver a dibujar un solo objeto, antes de que canvasbuildbatch calcule qué elementos deben reconstruirse,
se menciona en el método PerformUpdate de CanvasUpdateRegistry que hay tres partes principales

1) Reconstrucción del diseño

Implica muchos cálculos. Por ejemplo, el diseño anidado causará una mayor pérdida de rendimiento, porque se calcula capa por capa. Solo después del cálculo de la capa anterior se puede realizar el cálculo de la siguiente capa, especialmente cuando solo hay dos o tres artículos Es mejor usar código para hacer cálculos y evitar usar componentes de ordenación automática

2). Recortar

3).Reconstrucción gráfica

La razón para generar marcas sucias para vértices y materiales
es muy simple, solo cuando se cambia el material, se marcará
por muchas razones, en la clase Graphic, SetVerticesDirty (establecer los vértices en ese método de marca), verifique sus referencias, puede ver que hay muchas referencias, por ejemplo, un pequeño cambio de atributo en la imagen causará la marca sucia del vértice y provocará la reconstrucción.Se llamará a SetAllDirty en OnEnable y OnDisable de Graphic, y establecerá que todas las banderas sucias estén activadas
imagen.png
en
controle directamente los componentes y la pérdida de rendimiento de los objetos es grande porque se llama a este método, por lo que los componentes y los objetos se volverán a dibujar cuando se muestren y se oculten.Evite llamar al método SetActive de objetos

3. Proceso de ejecución de la reconstrucción

Ejemplo de configuración de color con Imagen

//  Graphic类中color属性,设置时会先调用SetPropertyUtility.SetColor,成功之后设置脏标记
public virtual Color color {
    
     
     get {
    
     return m_Color; } 
     set {
    
     
     	if (SetPropertyUtility.SetColor(ref m_Color, value)) 
            SetVerticesDirty(); 
     } 
 }
// SetPropertyUtility.SetColor : 颜色修改
 public static bool SetColor(ref Color currentValue, Color newValue)
 {
    
    
     //判断与之前的颜色是都一致,一致则不需要重建
     if (currentValue.r == newValue.r && currentValue.g == newValue.g && currentValue.b == newValue.b && currentValue.a == newValue.a)
         return false;

     currentValue = newValue;
     return true;
 }
//SetVerticesDirty : 调用CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild
//传入需要重建的Graphic
public virtual void SetVerticesDirty()
{
    
    
    if (!IsActive())
        return;

    m_VertsDirty = true;
    CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this);

    if (m_OnDirtyVertsCallback != null)
        m_OnDirtyVertsCallback();
}
//CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild : 将传入的Graphic加入队列中
public static void RegisterCanvasElementForGraphicRebuild(ICanvasElement element)
{
    
    
    instance.InternalRegisterCanvasElementForGraphicRebuild(element);
}
private bool InternalRegisterCanvasElementForGraphicRebuild(ICanvasElement element)
{
    
    
    if (m_PerformingGraphicUpdate)
    {
    
    
        Debug.LogError(string.Format("Trying to add {0} for graphic rebuild while we are already inside a graphic rebuild loop. This is not supported.", element));
        return false;
    }

    return m_GraphicRebuildQueue.AddUnique(element);
}
//CanvasUpdateRegistry构造函数注册了Canvas.willRenderCanvases += PerformUpdate
//下一帧canvasrender时会调用PerformUpdate就会进行加入的Graphic重建

En resumen:
es la modificación del objeto lo que hace que se marque con una marca sucia, para luego reconstruir el Gráfico del objeto marcado sobre esa marca

4. Ideas de optimización

La reconstrucción del lienzo es la que lleva más tiempo. Hay muchas cosas debajo, por lo que modificar uno de los componentes reconstruirá todos los componentes en él. Si hay muchos otros componentes que no se modificarán, como el fondo , pero debido a la modificación de otros componentes, los cambios de componentes que no necesitan ser modificados con frecuencia causarán un consumo de rendimiento irrazonable
o hay muchos textos en la pantalla, luego controlar la visualización y ocultar uno de los textos hará que todos los textos a reconstruir, lo que provocará que Dayton se atasque, porque hay muchas caras y vértices en el texto

3. Lógica de ejecución de la parte del rayo de la interfaz de usuario

El componente principal es GraphicRaycaster (en Canvas).En
comparación con los rayos ordinarios, la mayor diferencia es que solo responde a los objetos que heredan la clase Graphic y se trata como rayos de interfaz de usuario.

//主要是Raycast方法 : 代码太多,只截取部分代码
//获取当前canvas所有Graphics组件
 var canvasGraphics = GraphicRegistry.GetGraphicsForCanvas(canvas);
//响应点击事件的摄像机
var currentEventCamera = eventCamera; 
//获取canvas上设置的targetDisplay : 显示在第几个显示器上
if (canvas.renderMode == RenderMode.ScreenSpaceOverlay || currentEventCamera == null)
    displayIndex = canvas.targetDisplay;
else
    displayIndex = currentEventCamera.targetDisplay;
//将点击位置转换成相对于显示器屏幕的坐标(计算Pos属性)
 //判断点击Pos转换到屏幕坐标的结果是否超出了屏幕
if (pos.x < 0f || pos.x > 1f || pos.y < 0f || pos.y > 1f)
    return;
//根据GraphicRaycaster上的Blocking Mask属性判断射线击中的距离(计算hitDistance属性)
//射线的主要逻辑 : 对当前Graphics的状态进行筛选
Raycast(canvas, currentEventCamera, eventPosition, canvasGraphics, m_RaycastResults);

 //graphic深度为-1时不会被绘制在屏幕上,即物体的activeInHierarchy为false
//graphic.raycastTarget : UI元素是否进行射线碰撞响应
//graphic.canvasRenderer.cull : 当前canvasrender是否被剔除,如果为true也不会绘制
if (graphic.depth == -1 || !graphic.raycastTarget || graphic.canvasRenderer.cull)
    continue;
//筛选点击时间是否在graphic的rectTransform上
if (!RectTransformUtility.RectangleContainsScreenPoint(graphic.rectTransform, pointerPosition, eventCamera))
    continue;
//筛选Z的租表是否超出了相机的最远面
if (eventCamera != null && eventCamera.WorldToScreenPoint(graphic.rectTransform.position).z > eventCamera.farClipPlane)
    continue;
//根据深度对数组进行逆序
s_SortedGraphics.Sort((g1, g2) => g2.depth.CompareTo(g1.depth));
totalCount = s_SortedGraphics.Count;
for (int i = 0; i < totalCount; ++i)
    results.Add(s_SortedGraphics[i]);

 //判断当前是否是一个反面目标
if (ignoreReversedGraphics)
//过滤摄像机背后渲染的元素
if (appendGraphic)
//再判断距离
if (distance >= hitDistance)
	continue;
//得到真正的击中目标
resultAppendList.Add(castResult);

4. Lote UGUI

El procesamiento por lotes significa que las interfaces de usuario que pueden fusionar mallas se combinan entre sí. La interfaz de usuario se construye de atrás hacia adelante, y el orden en el panel es el nivel de representación.

1. Reglas de lotes

Primero ordene todas las interfaces de usuario de acuerdo con la profundidad de la interfaz de usuario, la identificación del material, la identificación de la textura y el orden de procesamiento, y luego realice el procesamiento por lotes, es decir, juzgue si el material y la textura son iguales y, si son iguales, se pueden procesar por lotes. Nota aquí: Aquellos que se pueden
agrupar Los elementos deben estar uno al lado del otro UI1 y UI2 se pueden fusionar, pero UI1 y UI3 no se pueden agrupar, porque UI2 interrumpe el procesamiento por lotes, por lo que el orden de representación de la UI es muy
importante para evitar que se interrumpa la dosificación.

2. Ejemplo de análisis de reglas de procesamiento por lotes

Cuanto menor sea la profundidad, el primero en representar
imagen.png


1). Desde el primer objeto blanco, juzgue si la profundidad es -1 (si se muestra el objeto). Si no se muestra, continúe juzgando la profundidad del siguiente objeto. Si se muestra, juzgue si cubre otros objetos. La imagen de arriba muestra que el blanco no está cubierto en otros objetos, por lo que su profundidad es 0 2). El
texto está cubierto en blanco. Lo especial del texto es que el marco puede ser más grande que la malla,
imagen.png
por lo que la condición para cubrir aquí no es que los marcos exteriores se superpongan. En cambio, depende de si las mallas de las dos interfaces de usuario se superponen
y, si están cubiertas, determinar si las dos se pueden combinar (ya sea el Material y la Textura). son iguales), aquí es obvio que no se pueden combinar, por lo que el valor de profundidad del texto profundidad = valor de profundidad blanco + 1 = 1
Si muchos están cubiertos, entonces el valor de profundidad del texto = el mayor valor de profundidad en el cubierto elemento + 1
3) el rojo está cubierto sobre el blanco y el texto, y el rojo y el texto no se pueden combinar, el valor de profundidad del texto y el blanco El más grande es el texto, por lo que la profundidad del rojo = profundidad del texto + 1 = 2 4)
. el amarillo está cubierto sobre el rojo y se puede agrupar, y su profundidad es 2 (tenga en cuenta que esto es solo una prueba por lotes, no una operación por lotes real) 5) el azul está
cubierto sobre el amarillo y se puede agrupar, y su profundidad es 2
6). De acuerdo con la profundidad, hay tres matrices con una profundidad de 2. En este momento, clasifique las que tienen la misma profundidad, ID de material, Textura Las ID son todas iguales, y finalmente ordene según al orden de procesamiento, por lo que la matriz final es: blanco - texto - rojo - amarillo - azul
7). La matriz se pasará a la parte de procesamiento por lotes. Después de pasar, se juzgará a partir del primer elemento si se puede combinar con elementos adyacentes para juzgar si se puede combinar (donde se realiza realmente el lote), y W y T no se pueden combinar. , su número de lote es 0, de manera similar, el número de lote de T es 1, R e Y se pueden agrupar juntos, continúe juzgando que el siguiente B también se puede agrupar, por lo que el número de lote de RYB es 2

Resumen:
1) Atravesar todos los elementos de la interfaz de usuario
2) Ordenar la matriz según la profundidad de la interfaz de usuario, la identificación del material, la identificación de la textura y el orden de procesamiento
3) Filtrar todos los elementos de la interfaz de usuario con un valor de profundidad de -1
4) Juzgar si son adyacentes los elementos son Combinar lotes para obtener el número de lote

3.Frame Debug (herramienta de visualización de orden de renderizado)

imagen.png

4. Módulo de interfaz de usuario en Profiler: puede verificar el motivo de la interrupción del procesamiento por lotes

imagen.png
Gameobject Count: el número de gameobjects contenidos en el lote actual

5. Ejemplo especial de procesamiento por lotes

imagen.png
Resultados por lotes: tres lotes de texto, blanco y azul. Debido a que la matriz ordenada es W -T -B, esto se debe a que el ID de textura de W es más pequeño, por lo que cuando se ordenan T y W, W está al frente. El método consiste en asignar la misma textura a los componentes de la imagen de W y B, de modo que T no interrumpa el procesamiento por lotes de W y B.

6. La máscara no se puede agrupar por lotes

1). La máscara generará 2 sorteos, que es la razón de su consumo de rendimiento.

1. Configure el caché de plantilla
para agregar un material especial a la máscara, razón por la cual se interrumpe el procesamiento por lotes. Debido a que el material es diferente, configure el valor de caché de plantilla del píxel que debe ocultarse en 0 y configure el caché de plantilla valor del píxel que debe mostrarse 1, esta es la primera llamada de dibujo
2. Después de atravesar los subobjetos debajo de la máscara, la memoria caché de la plantilla se restaurará, por lo que
se genera otro material de llamada de dibujo. se juzga si el valor de caché de la plantilla del píxel es 1 para decidir si renderizar, la restauración es el segundo drawcall

2) La máscara interrumpirá el procesamiento por lotes, porque la máscara recibirá un material especial

3) Las máscaras se pueden agrupar por lotes (siempre que las identificaciones de las imágenes sean las mismas)

Debido a que la máscara genera dos sorteos, las dos máscaras se pueden agrupar en el sorteo establecido, y el sorteo restaurado se puede agrupar juntos. En general, todavía hay dos sorteos. Nota: 1). La cámara generará un sorteo


2
)
. El componente de máscara está colgado Debe haber un componente de imagen en el objeto, de lo contrario no tendrá efecto
3). El objeto ocluido todavía está dibujado, lo que tomará una llamada de dibujo, pero la máscara eliminará los píxeles dibujados
4). Los subobjetos debajo de la máscara se pueden agrupar normalmente 5
). Se pueden agrupar dos máscaras, y los subobjetos de las dos máscaras que se pueden agrupar también se pueden agrupar.
imagen.png
6) Cuando la siguiente máscara se superpone con el sub-objeto oculto objetos de la máscara anterior, porque el subobjeto oculto por la máscara anterior interrumpió el procesamiento por lotes de las dos máscaras, por lo que la siguiente máscara calculará el sorteo por separado y no se puede procesar por lotes
imagen.png

7.RectMask2D

Ahorra más rendimiento que la máscara
1). RectMask2D en sí mismo no ocupa drawcall. De hecho, solo usa el área del objeto actual para recortar el subobjeto. No ocupa drawcall en sí. 2
) . Los vértices y las caras del objeto que están completamente recortados en la máscara todavía se dibujan normalmente. Sin embargo, los objetos que están completamente recortados por RectMask2D no dibujarán vértices y caras, y no ocuparán drawcalls 3)
. RectMask2D no participará en el cálculo de profundidad entre otras interfaces de usuario y no se puede agrupar en
lotes.4) Las subclases en RectMask2D Objects se pueden agrupar en lotes o se pueden agrupar en lotes con un solo objeto (no hay ninguna restricción de RectMask2D arriba), pero no se pueden agrupar en lotes. con otro subobjeto bajo RectMask2D

En comparación con la máscara:
el mayor problema con RectMask2D es que dos RectMask2D no se pueden agrupar por lotes, por lo que se deben seleccionar diferentes métodos de enmascaramiento de acuerdo con diferentes escenarios de uso
1. Hay varias máscaras y los subobjetos debajo de la máscara son Puede elegir use la máscara 2 en lotes
Si solo hay una máscara y es solo una máscara para la interfaz de usuario, usar RectMask2D ahorrará rendimiento

Cinco Tasa de llenado

Cuantas más veces se dibuje un píxel, más brillante será el color
Intente evitar la cobertura de la interfaz de usuario y también evite separar todo el contenido.
Utilice imágenes con formas especiales para las imágenes de la interfaz de usuario, ya que esto puede reducir el área efectiva y la cobertura. Por ejemplo, una imagen circular generalmente se corta en un rectángulo. No es necesario mostrar un área transparente a su alrededor, pero esto aumentará el área efectiva y aumentará la posibilidad de cobertura de la interfaz de usuario.

1) Puede usar Jiugongge para ahuecar la parte central para reducir la tasa de llenado

imagen.png


El componente Imagen necesita establecer el tipo de imagen:
imagen.png
el vaciado irregular requiere el uso de scripts, que se explicarán en detalle más adelante.

2) Desaprobar el componente de efecto de texto

Por ejemplo, el contorno y la sombra aumentarán una gran cantidad de vértices y caras, y el efecto no es el ideal.
imagen.png
Cambie el valor a un valor mayor y podrá ver que hay cuatro textos nuevos a la izquierda, lo que significa que ha aumentado. el número de vértices y caras por 4 veces para lograr el efecto de trazo. El número de caras
puede usar el complemento Text Mesh Pro para lograr el trazo y otros efectos

Supongo que te gusta

Origin blog.csdn.net/dengshunhao/article/details/105404086
Recomendado
Clasificación