Единство: подходит размер родителей к размеру детей - PullRequest
0 голосов
/ 06 февраля 2019

У меня есть пустой элемент Canvas, в котором есть несколько объектов в качестве дочерних элементов.Больше детей добавляется к родителю по ходу игры.Я хочу, чтобы родитель соответствовал по размеру своим дочерним элементам.

Я уже много читал об этой теме, но каждый раз сталкивался с ContentSizeFitter, который, к сожалению, не работает для меня, потому что ему нужна группа макетов, которого у меня нет, потому что дети не имеют порядка и находятся в диком состоянии.

Я использую Unity 2018.3.4f1 Personal.

Родитель не по размеру:

Example

Размер родительского элемента (красный: новый, зеленый: старый):

Example 2

Структура:

Canvas
 |- Empty
     |- Child 1
     |- Child 2
     |- Child X

Ответы [ 3 ]

0 голосов
/ 06 февраля 2019

Нечто подобное должно работать.Он перебирает все дочерние объекты выбранного вами объекта, затем находит границы рендеринга этих объектов и обновляет минимальное и максимальное значения.В конце функции Start () переменные min и max содержат координаты углов поля, определяющего границы.

public class NewBehaviourScript : MonoBehaviour
{
    void Start ()
    {
        Vector2 min = new Vector2 (0, 0);
        Vector2 max = new Vector2 (0, 0);

        GetParentBounds (gameObject, out min, out max);
        Debug.Log (min);
        Debug.Log (max);

    }

    void GetParentBounds (GameObject GO, out Vector2 pMin, out Vector2 pMax)
    {
        Transform[] ts = GO.GetComponentsInChildren<Transform> ();

        Vector2 parentMin = new Vector2 (float.MaxValue, float.MaxValue);
        Vector2 parentMax = new Vector2 (float.MinValue, float.MinValue);

        foreach (Transform t in ts) {
            Renderer rend = t.GetComponent<Renderer> ();
            if (rend != null) {
                Vector2 min = rend.bounds.min;
                Vector2 max = rend.bounds.max;
                Debug.Log (string.Format ("[{0}, {1}], [{2}, {3}]", min.x, min.y, max.x, max.y));
                parentMin.x = Mathf.Min (parentMin.x, min.x);
                parentMin.y = Mathf.Min (parentMin.y, min.y);
                parentMax.x = Mathf.Max (parentMax.x, max.x);
                parentMax.y = Mathf.Max (parentMax.y, max.y);
            }
        }

        pMin = parentMin;
        pMax = parentMax;
    }
}
0 голосов
/ 07 февраля 2019

Я написал небольшой кусочек кода, который выполняет свою работу или делает так, как я хочу, и мне этого достаточно:

using UnityEngine;

public class SizeFitter : MonoBehaviour {
    public void CheckForChanges() {
        RectTransform children = transform.GetComponentInChildren<RectTransform>();

        float min_x, max_x, min_y, max_y;
        min_x = max_x = transform.localPosition.x;
        min_y = max_y = transform.localPosition.y;

        foreach (RectTransform child in children) {
            Vector2 scale = child.sizeDelta;
            float temp_min_x, temp_max_x, temp_min_y, temp_max_y;

            temp_min_x = child.localPosition.x - (scale.x / 2);
            temp_max_x = child.localPosition.x + (scale.x / 2);
            temp_min_y = child.localPosition.y - (scale.y / 2);
            temp_max_y = child.localPosition.y + (scale.y / 2);

            if (temp_min_x < min_x)
                min_x = temp_min_x;
            if (temp_max_x > max_x)
                max_x = temp_max_x;

            if (temp_min_y < min_y)
                min_y = temp_min_y;
            if (temp_max_y > max_y)
                max_y = temp_max_y;
        }

        GetComponent<RectTransform>().sizeDelta = new Vector2(max_x - min_x, max_y - min_y);
    }
}
0 голосов
/ 06 февраля 2019

Я думаю, что вы можете найти самую левую границу и самую правую границу, а затем добавить разницу этого значения как sizeDelta родительского RectTransform.

Это должно исправить размер (повторите с верхним и верхнимнижний для Y).

Для позиции вы можете получить верхний левый угол с самой левой границей и верхней границей в Vector2, затем вы установите этот вектор как anchoredPosition для родительского RectTransform.

Обратите внимание, что шарнир родителя должен быть в верхнем левом углу, чтобы это работало.

Этот код только приблизился к чему-то, но он недостаточно хорош.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FitParentToChildren : MonoBehaviour
{
    #region INTERNAL

    public RectTransform parent;
    public RectTransform[] children;

    public float minX = 100000;
    public float maxX = -100000;
    public float minY = 100000;
    public float maxY = -100000;

    #endregion

    #region INITIALIZATION

    void Awake()
    {
        parent = GetComponent<RectTransform>();
        children = GetComponentsInChildren<RectTransform>();
    }

    void Start()
    {
        SetMinMaxValues();
        FitToChildren();
    }

    #endregion

    #region BEHAVIOURS

    private void FitToChildren()
    {
        parent.sizeDelta = GetNewRect();
        parent.anchoredPosition = GetTopLeftCornerPositon();
    }

    private void SetMinMaxValues()
    {
        for (int i = 1; i < children.Length; i++)
        {
            float tempMinX = children[i].anchoredPosition.x - children[i].sizeDelta.x / 2;
            if (tempMinX < minX) minX = tempMinX;

            float tempMaxX = children[i].anchoredPosition.x + children[i].sizeDelta.x / 2;
            if (tempMaxX > maxX) maxX = tempMaxX;

            float tempMinY = children[i].anchoredPosition.y - children[i].sizeDelta.y / 2;
            if (tempMinY < minY) minY = tempMinY;

            float tempMaxY = children[i].anchoredPosition.y + children[i].sizeDelta.y / 2;
            if (tempMaxY > maxY) maxY = tempMaxY;
        }
    }

    private Vector2 GetNewRect()
    {
        return new Vector2 (maxX - minX, maxY - minY);
    }

    private Vector2 GetTopLeftCornerPositon()
    {
        return new Vector2 (minX, maxY);
    }

    #endregion
}

GIF ЗДЕСЬ

enter image description here

...