Puntos de conocimiento de Unity sobre el foso de ForceRebuildLayoutImmediate

El Sr. Panda Xiao renunció hace un mes y para cumplir su sueño (crear un juego), comenzó a trabajar duro en su propio juego en su habitación todos los días. (en realidad jugando todos los días)

Hoy hablaré principalmente de dos temas. Como todos sabemos, la planificación es una discapacidad mental. (Espera, ahora soy medio planificador...) ​A menudo hay diseños anidados en diseños adaptables, y luego el texto de subnivel y las imágenes subsiguientes también son adaptables, y más adaptables En esta situación...
inserte la descripción de la imagen aquí
Siinserte la descripción de la imagen aquí
calcule la posición correcta usted mismo, obviamente no es científico, requiere mucho cerebro, la eficiencia es muy baja y el proceso de depuración hará que la gente se bloquee. Unity pensó oficialmente en esta situación, por lo que proporciona el método LayoutRebuilder.ForceRebuildLayoutImmediate(RectTransform). Es posible forzar un rediseño.
inserte la descripción de la imagen aquí

Pero Unity es un tipo duro, algunos métodos son realmente suficientes, al igual que la herramienta de edición nunca se ha vuelto a hacer después de 5.0... Solo utilícela)
Este método realmente solo recalcula la posición del componente secundario. No activa un nuevo diseño dentro del componente secundario.

Por lo tanto, para hacer frente a tal autoadaptación en la autoadaptación, existen dos soluciones.
Una es ejecutar un método para cada componente que necesita ser rediseñado, en este caso es un poco engorroso.

public void Test()
{
    
    
    LayoutRebuilder.ForceRebuildLayoutImmediate(layout1.GetComponent<RectTransform>());
    LayoutRebuilder.ForceRebuildLayoutImmediate(layout2.GetComponent<RectTransform>());
    LayoutRebuilder.ForceRebuildLayoutImmediate(layout3.GetComponent<RectTransform>());
}

La otra es buscar recursivamente este componente, y todos los componentes con LayoutGroup realizan un rediseño, pero esto requiere un poco de consumo. (Después de todo, el consumo de GetComponent no es muy bueno)

public void Test()
{
    
    
    List<Transform> transList = GetAllChildsByComponent(root.transform);
    foreach (Transform trans in transList)
    {
    
    
        RectTransform rectTrans = root.GetComponent<RectTransform>();
        if (null != rectTrans)
        {
    
    
            LayoutRebuilder.ForceRebuildLayoutImmediate(rectTrans);
        }
    }
}

public static List<Transform> GetAllChildsByComponent(Transform trans, List<Transform> transList = null)
{
    
    
    if (null == transList)
    {
    
    
        transList = new List<Transform>();
    }
    if (null != trans)
    {
    
    
        for (int i = 0; i < trans.childCount; i++)
        {
    
    
            Transform child = trans.GetChild(i);
            if (null != child.GetComponent<LayoutGroup>())
            {
    
    
                transList.Add(child);
            }
            GetAllChildsByComponent(child, transList);
        }
    }
    return transList;
}

Cuando haya terminado con estos, querrá probarlo, pero aún no lo ha cepillado. (El blogger está mintiendo, simplemente entiérrelo)
...
Esto implica el segundo problema: si vuelve a diseñar cuando cambian los vértices de sus componentes, es posible que no funcione.
Lo siguiente es una conjetura: el ajustador de tamaño de contenido del componente es el vértice recalculado en el mismo cuadro, y la reconstrucción que debería haberse activado está en el mismo cuadro siguiente. En este momento, la visualización es incorrecta, pero la reconstrucción cree que es lógicamente correcta. (No encontré bibliografía ni explicaciones, es pura conjetura personal, si alguien sabe, espero que me lo pueda decir, para poder entender este tema...)

La solución a esto es más simple. También dos.
El primero, existe la premisa de que hay un administrador de temporizador en el proyecto, solo retrase un cuadro y luego ejecútelo.
Este es el temporizador en mi proyecto, funcionalmente se ejecutará en el segundo cuadro.

public void Test()
{
    
    
    Timer timer = new Timer("Test");
    if (null != timer)
    {
    
    
        timer.SetDelayer(0.01, () =>
        {
    
    
            LayoutRebuilder.ForceRebuildLayoutImmediate(layout.GetComponent<RectTransform>());
        });
    }
}

De lo contrario, use la corrutina WaitForEndOfFrame o en Update para asegurarse de que se ejecute en el siguiente cuadro.
El método Actualizar aquí no es una panacea, sino una solución.

void Update()
 {
    
    
    if (null != layout)
    {
    
    
        if (!isRun)
        {
    
    
            isRun = !isRun;
        }
        else
        {
    
    
            LayoutRebuilder.ForceRebuildLayoutImmediate(layout.GetComponent<RectTransform>());
            isRun = false;
            layout = null;
        }
    }
}

Y la solución de la rutina

public void Test()
{
    
    
    StartCoroutine(TestEnumerator(layout.GetComponent<RectTransform>()));
}

private IEnumerator TestEnumerator(RectTransform rectTrans)
{
    
    
    yield return new WaitForEndOfFrame();
    LayoutRebuilder.ForceRebuildLayoutImmediate(rectTrans);
}

El anterior es el problema que pasé tres horas localizando y resolviendo hoy (incluida la extensión del temporizador y la creación de un administrador de rutinas), lo que realmente me retrasó para celebrar el resto del año. Espero que todos puedan ver este hoyo y caminar alrededor de él.

feliz año nuevo ~

Supongo que te gusta

Origin blog.csdn.net/qql7267/article/details/104026135
Recomendado
Clasificación