유니티에서도 Grid Layout Group 컴포넌트가 존재하긴 합니다. 하지만 해당 컴포넌트를 사용하면 각 행과 열의 Element이 Grid 형태에서 벗어나지 못한다는 문제가 있습니다(뭔 소리야 ㅋㅋ..그러려고 Grid Layout Group 컴포넌트 쓰는건데!)
워워... 그 뜻이 아니라 Grid란 사전 의미를 찾아보면 다음과 같습니다.
수평선과 수직선이 교차해서 이루어진 집합체이다. 하나의 집합체는 세로 열을 그리고 다른 하나는 가로 행을 정의합니다. 각 요소는 이러한 열과 행으로 된 라인으로 배치할 수 있다.
즉, 위와 같은 조건을 충족만 하면 Grid라 할 수 있는거죠. 유니티의 Grid Layout Group 컴포넌트는 Grid 조건을 만족하지만 정해져 있는 모습을 벗어나지 못한다는 점입니다...
각 행의 Element개수를 다르게 하거나 각 행마다 margin, Spacing을 다르게 할 수 없다는 뜻이죠!
그래서 Custom Grid Layout 컴포넌트를 제작해봤습니다.
Custom Grid Layout
Custom Grid Layout 컴포넌트를 사용하면 위 사진과 같이 각 행의 Element들을 컨트롤 할 수 있습니다.
Spacing과 Margin값이 큰 이유로는.. Rect Transform의 Width와 Height를 너무 작게 설정해서 그런거긴 합니다.
코드
using UnityEngine;
public enum AnchorPoint
{
TopLeft,
MiddleCenter
}
public class CustomGridLayout : MonoBehaviour
{
public int Rows;
public int[] ElementsPerRow;
public Vector2[] Spacing;
public Vector2[] Margin;
public AnchorPoint anchorPoint;
public Vector2 Offset;
private RectTransform rectTransform;
private void Start()
{
rectTransform = GetComponent<RectTransform>();
ArrangeElements();
}
public void ArrangeElements()
{
int childCount = transform.childCount;
if (ElementsPerRow.Length != Rows || Spacing.Length != Rows || Margin.Length != Rows)
{
Debug.LogError("ElementsPerRow, Spacing, Margin arrays must have the same length as Rows.");
return;
}
float containerWidth = rectTransform.rect.width;
float containerHeight = rectTransform.rect.height;
int currentElement = 0;
for (int row = 0; row < Rows; row++)
{
int elementsInThisRow = ElementsPerRow[row];
if (elementsInThisRow == 0) continue;
float totalSpacingX = (elementsInThisRow - 1) * Spacing[row].x;
float totalMarginX = Margin[row].x * 2;
float elementWidth = (containerWidth - totalSpacingX - totalMarginX) / elementsInThisRow;
float elementHeight = 0;
for (int i = currentElement; i < currentElement + elementsInThisRow && i < childCount; i++)
{
RectTransform childRect = transform.GetChild(i).GetComponent<RectTransform>();
if (childRect.rect.height > elementHeight)
{
elementHeight = childRect.rect.height;
}
}
float totalSpacingY = (Rows - 1) * Spacing[row].y;
float totalMarginY = Margin[row].y * 2;
float rowHeight = elementHeight + totalSpacingY + totalMarginY;
for (int col = 0; col < elementsInThisRow; col++)
{
if (currentElement >= childCount)
{
return;
}
Transform child = transform.GetChild(currentElement);
RectTransform childRect = child.GetComponent<RectTransform>();
float xPos = Margin[row].x + col * (elementWidth + Spacing[row].x);
float yPos = 0;
switch (anchorPoint)
{
case AnchorPoint.TopLeft:
yPos = -Margin[row].y - row * (rowHeight + Spacing[row].y);
break;
case AnchorPoint.MiddleCenter:
yPos = containerHeight / 2 - Margin[row].y - row * (rowHeight + Spacing[row].y) -
elementHeight / 2;
xPos -= containerWidth / 2;
break;
}
childRect.anchoredPosition = new Vector2(xPos, yPos) + Offset;
childRect.sizeDelta = new Vector2(elementWidth, elementHeight);
currentElement++;
}
}
}
#if UNITY_EDITOR
private void OnValidate()
{
if (rectTransform != null)
{
ArrangeElements();
}
}
#endif
}
코드를 멋있게 커스터마이징해서 공유해주세요!
더 많은 기능을 추가할 수 있다고 생각합니다.
감사합니다.