想要所有子物体等于缩放:Achors 和 Pivot
子物体锚定 一个父物体的 百分比坐标,这样会保证子物体跟随父物体等比缩放。所以说,当父物体的缩放出问题了,子物体就算锚定对了也会出问题。注意子物体锚定的时候用的是自身坐标,而非父物体的坐标。
最简单便于理解 和 直观的操作:把pivot全设置到左下角。如图:123正方形image。
1的RectTransform:(注意pivot和anchor,很一般,都是默认的)
2 和 3 的
几乎一模一样。pivot都在左下角,anchor的min和max 分别就是:x:0_0.5 y:0.5_1 了。很明显能看出来,min和max的意思就是,以自身的pivot为起点,锚定到父物体大小的百分比。
进而知道这个特性后,其实有个特别好的ui流程:
先试用这种锚定方式(很直观的把UI拼好),然后写个工具在编辑器下或者加载的时候实时算出 要等比缩放的物体 在锚定在父物体的位置。
设置position时从父物体递归,因为,子物体都是相对位置。
设置anchor时从子物体开始递归设置,因为子物体的RectTransform依赖父物体的,一旦设置了父物体的rect,子物体获取的数据就无法保证计算一致。
统一处理的代码:
public partial class BuildingWindowEditor
{
RectTransform[] rts;
GameObject go;
Dictionary<Transform, Vector3> cache = new Dictionary<Transform, Vector3>();
private void BuildingUI()
{
GUILayout.Box("设置 选中的UI的子物体 跟随选中节点进行等比缩放。");
if (GUILayout.Button("access"))
{
cache.Clear();
go = Selection.activeGameObject;
if (go == null)
{
Debuger.LogError(" selection is null");
return;
}
rts = go.GetComponentsInChildren<RectTransform>(true);
foreach (var item in rts)
{
var prt = item.parent.GetComponent<RectTransform>();
if (prt == null)
{
continue;
}
Vector2 parentPivot = prt.pivot;
Vector2 curPivot = item.pivot;
Vector3 deltaPos = item.position - prt.position;
Vector3 delta = new Vector3(parentPivot.x * prt.rect.width, parentPivot.y * prt.rect.height, 0) -
new Vector3(curPivot.x * item.rect.width, curPivot.y * item.rect.height, 0) + deltaPos;
cache.Add(item, delta);
}
RemakeChildPos(go.GetComponent<RectTransform>());
RemakChildAnchor(go.GetComponent<RectTransform>(), null);
}
}
void RemakeChildPos(RectTransform cur)
{
if (cur == null || !cache.ContainsKey(cur))
{
return;
}
var prt = cur.parent.GetComponent<RectTransform>();
cur.pivot = Vector2.zero;
cur.position = cache[cur] + prt.position;
for (int i = 0; i < cur.childCount; i++)
{
RemakeChildPos(cur.GetChild(i).GetComponent<RectTransform>());
}
}
void RemakChildAnchor(RectTransform cur, RectTransform parent)
{
if (cur == null)
{
return;
}
for (int i = 0; i < cur.childCount; i++)
{
RemakChildAnchor(cur.GetChild(i).GetComponent<RectTransform>(), cur);
}
if (cur.name == go.name)
{
return;
}
if (parent == null)
{
return;
}
Debuger.LogError(cur.name + " *** " + parent.name);
float deltaX = (cur.position - parent.position).x;
float deltaY = (cur.position - parent.position).y;
Vector2 X = new Vector2(deltaX, deltaX + cur.rect.width) / parent.rect.width;
Vector2 Y = new Vector2(deltaY, deltaY + cur.rect.height) / parent.rect.height;
Debuger.LogError(string.Format("{0} {1} {2} {3} {4}", deltaX, deltaY, cur.rect, parent.rect, cur.localPosition));
cur.anchorMin = new Vector2(X.x < X.y ? X.x : X.y,
Y.x < Y.y ? Y.x : Y.y);
cur.anchorMax = new Vector2(X.x > X.y ? X.x : X.y,
Y.x > Y.y ? Y.x : Y.y);
cur.offsetMin = Vector2.zero;
cur.offsetMax = Vector2.zero;
}
}