请在ugui下实现一个和VerticalLayoutGroup功能一样的,性能非常好的脚本,Anchors与pivot可以随意设置
时间: 2024-05-09 22:16:16 浏览: 143
好的,我可以帮你实现一个自定义的LayoutGroup脚本,功能和VerticalLayoutGroup类似,但是性能更好,并且可以随意设置Anchors与Pivot。
首先,我们需要继承自LayoutGroup类,并实现其主要的方法:
```csharp
using UnityEngine;
using UnityEngine.UI;
[ExecuteInEditMode]
public class CustomVerticalLayoutGroup : LayoutGroup
{
[SerializeField] private bool m_ChildForceExpandWidth = true;
[SerializeField] private bool m_ChildForceExpandHeight = false;
[SerializeField] private bool m_ChildControlWidth = true;
[SerializeField] private bool m_ChildControlHeight = true;
[SerializeField] private bool m_PaddingUseCustom = false;
[SerializeField] private Vector2 m_PaddingCustom = Vector2.zero;
[SerializeField] private float m_Spacing = 0f;
public bool childForceExpandWidth { get { return m_ChildForceExpandWidth; } set { SetProperty(ref m_ChildForceExpandWidth, value); } }
public bool childForceExpandHeight { get { return m_ChildForceExpandHeight; } set { SetProperty(ref m_ChildForceExpandHeight, value); } }
public bool childControlWidth { get { return m_ChildControlWidth; } set { SetProperty(ref m_ChildControlWidth, value); } }
public bool childControlHeight { get { return m_ChildControlHeight; } set { SetProperty(ref m_ChildControlHeight, value); } }
public bool paddingUseCustom { get { return m_PaddingUseCustom; } set { SetProperty(ref m_PaddingUseCustom, value); } }
public Vector2 paddingCustom { get { return m_PaddingCustom; } set { SetProperty(ref m_PaddingCustom, value); } }
public float spacing { get { return m_Spacing; } set { SetProperty(ref m_Spacing, value); } }
protected override void OnEnable()
{
base.OnEnable();
SetDirty();
}
protected override void OnDisable()
{
base.OnDisable();
SetDirty();
}
public override void CalculateLayoutInputVertical()
{
base.CalculateLayoutInputVertical();
float totalHeight = paddingUseCustom ? paddingCustom.y : padding.top + padding.bottom;
for (int i = 0; i < rectChildren.Count; i++)
{
RectTransform child = rectChildren[i];
totalHeight += LayoutUtility.GetPreferredHeight(child) + spacing;
}
SetLayoutInputForAxis(totalHeight - spacing, totalHeight - spacing, -1, 1);
}
public override void SetLayoutVertical()
{
float innerHeight = rectTransform.rect.height - (paddingUseCustom ? paddingCustom.y : padding.top + padding.bottom);
float pos = paddingUseCustom ? paddingCustom.y : padding.top;
for (int i = 0; i < rectChildren.Count; i++)
{
RectTransform child = rectChildren[i];
float height = LayoutUtility.GetPreferredHeight(child);
float anchorY = child.pivot.y;
float pivotY = child.pivot.y;
Vector2 anchorMin = child.anchorMin;
Vector2 anchorMax = child.anchorMax;
if (childForceExpandHeight)
{
anchorMin.y = 0f;
anchorMax.y = 1f;
}
if (childControlHeight)
{
child.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height);
}
float width = childControlWidth ? LayoutUtility.GetPreferredWidth(child) : child.rect.width;
float pivotX = child.pivot.x;
Vector2 pivot = new Vector2(pivotX, pivotY);
Vector2 sizeDelta = new Vector2(width, height);
Vector2 anchoredPosition = new Vector2(pivotX * width, pos + (1f - anchorY) * height);
if (childForceExpandWidth)
{
anchorMin.x = 0f;
anchorMax.x = 1f;
}
child.anchorMin = anchorMin;
child.anchorMax = anchorMax;
child.pivot = pivot;
child.sizeDelta = sizeDelta;
child.anchoredPosition = anchoredPosition;
pos += height + spacing;
}
}
protected bool SetProperty<T>(ref T currentValue, T newValue)
{
if (currentValue == null && newValue == null)
return false;
if (currentValue != null && currentValue.Equals(newValue))
return false;
currentValue = newValue;
SetDirty();
return true;
}
protected void SetDirty()
{
if (!IsActive())
return;
LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
}
}
```
在这个自定义的LayoutGroup脚本中,我们增加了一些属性,比如:
- childForceExpandWidth:是否强制子元素扩展宽度。
- childForceExpandHeight:是否强制子元素扩展高度。
- childControlWidth:是否控制子元素宽度。
- childControlHeight:是否控制子元素高度。
- paddingUseCustom:是否使用自定义的Padding。
- paddingCustom:自定义的Padding。
- spacing:元素之间的间隔。
然后,我们实现了CalculateLayoutInputVertical()方法,该方法计算布局的垂直方向输入。我们首先计算总高度,包括所有子元素的高度和间隔。然后,我们调用SetLayoutInputForAxis()方法设置垂直方向的输入。
接着,我们实现了SetLayoutVertical()方法,该方法设置布局的垂直方向。我们首先计算布局内部的高度,然后设置每个子元素的位置、大小、锚点和中心点。最后,我们更新下一个子元素的位置。
最后,我们实现了SetProperty()和SetDirty()方法,这两个方法用于处理属性更改和标记布局为需要重建。
使用这个自定义的LayoutGroup脚本非常简单,只需要将其添加到任何具有RectTransform组件的GameObject上,并将其子元素添加到该GameObject中即可。你可以随意设置该脚本的各种属性,以满足你的需求。
阅读全文