Unity中 NGUI插件十分方便利用Anchor属性, 可以做出屏幕的适应,比如做个小地图一直在右上角,做个血量条一直在左上角。做个技能栏一直在屏幕正下方。其实在Unity 里的UGUI也可以很容易实现,但是呢,没有NGUI集成的多,不大方便,
在Unity中 修改Canvas 中的属性
这个是调整 sprite 的scale 不会被拉伸,然后再 调下Rect Transform中的锚点 Anchors 为右上角
小地图就是右上角, 技能栏就是 下方,然后再细调下Pivot
就可以做到自适应了,这个是UGUI 的设置
NGUI 呢 也是 修改Anchor的 属性
左上 就 是 血量, 右上也 只需要设置 Left Right 为Right,即可。
小地图 左右对应是center, 上下对应是下方; Anchors 锚点--就是 边框距离 外部的相对位置。 类似css中margin属性 不过margin 对应的是元素, 而NGUI中Anchor的Unified 类型对应的是整个屏幕,而高级 Advence里,可以有4个targer对应。
而具体的算法在 NGUIMath里面, AdjustWidget这个方法里
/// <summary>
/// Adjust the widget's rectangle based on the specified modifier values.
/// </summary>
static public void AdjustWidget (UIWidget w, float left, float bottom, float right, float top,
int minWidth, int minHeight, int maxWidth, int maxHeight)
{
Vector2 piv = w.pivotOffset;
Transform t = w.cachedTransform;
Quaternion rot = t.localRotation;
// We should be working with whole integers
int iLeft = Mathf.FloorToInt(left + 0.5f);
int iBottom = Mathf.FloorToInt(bottom + 0.5f);
int iRight = Mathf.FloorToInt(right + 0.5f);
int iTop = Mathf.FloorToInt(top + 0.5f);
// Centered pivot should mean having to perform even number adjustments
if (piv.x == 0.5f && (iLeft == 0 || iRight == 0))
{
iLeft = ((iLeft >> 1) << 1);
iRight = ((iRight >> 1) << 1);
}
if (piv.y == 0.5f && (iBottom == 0 || iTop == 0))
{
iBottom = ((iBottom >> 1) << 1);
iTop = ((iTop >> 1) << 1);
}
// The widget's position (pivot point) uses a different coordinate system than
// other corners. This is a source of major PITA, and results in a lot of extra math.
Vector3 rotatedTL = rot * new Vector3(iLeft, iTop);
Vector3 rotatedTR = rot * new Vector3(iRight, iTop);
Vector3 rotatedBL = rot * new Vector3(iLeft, iBottom);
Vector3 rotatedBR = rot * new Vector3(iRight, iBottom);
Vector3 rotatedL = rot * new Vector3(iLeft, 0f);
Vector3 rotatedR = rot * new Vector3(iRight, 0f);
Vector3 rotatedT = rot * new Vector3(0f, iTop);
Vector3 rotatedB = rot * new Vector3(0f, iBottom);
Vector3 offset = Vector3.zero;
if (piv.x == 0f && piv.y == 1f)
{
offset.x = rotatedTL.x;
offset.y = rotatedTL.y;
}
else if (piv.x == 1f && piv.y == 0f)
{
offset.x = rotatedBR.x;
offset.y = rotatedBR.y;
}
else if (piv.x == 0f && piv.y == 0f)
{
offset.x = rotatedBL.x;
offset.y = rotatedBL.y;
}
else if (piv.x == 1f && piv.y == 1f)
{
offset.x = rotatedTR.x;
offset.y = rotatedTR.y;
}
else if (piv.x == 0f && piv.y == 0.5f)
{
offset.x = rotatedL.x + (rotatedT.x + rotatedB.x) * 0.5f;
offset.y = rotatedL.y + (rotatedT.y + rotatedB.y) * 0.5f;
}
else if (piv.x == 1f && piv.y == 0.5f)
{
offset.x = rotatedR.x + (rotatedT.x + rotatedB.x) * 0.5f;
offset.y = rotatedR.y + (rotatedT.y + rotatedB.y) * 0.5f;
}
else if (piv.x == 0.5f && piv.y == 1f)
{
offset.x = rotatedT.x + (rotatedL.x + rotatedR.x) * 0.5f;
offset.y = rotatedT.y + (rotatedL.y + rotatedR.y) * 0.5f;
}
else if (piv.x == 0.5f && piv.y == 0f)
{
offset.x = rotatedB.x + (rotatedL.x + rotatedR.x) * 0.5f;
offset.y = rotatedB.y + (rotatedL.y + rotatedR.y) * 0.5f;
}
else if (piv.x == 0.5f && piv.y == 0.5f)
{
offset.x = (rotatedL.x + rotatedR.x + rotatedT.x + rotatedB.x) * 0.5f;
offset.y = (rotatedT.y + rotatedB.y + rotatedL.y + rotatedR.y) * 0.5f;
}
minWidth = Mathf.Max(minWidth, w.minWidth);
minHeight = Mathf.Max(minHeight, w.minHeight);
// Calculate the widget's width and height after the requested adjustments
int finalWidth = w.width + iRight - iLeft;
int finalHeight = w.height + iTop - iBottom;
// Now it's time to constrain the width and height so that they can't go below min values
Vector3 constraint = Vector3.zero;
int limitWidth = finalWidth;
if (finalWidth < minWidth) limitWidth = minWidth;
else if (finalWidth > maxWidth) limitWidth = maxWidth;
if (finalWidth != limitWidth)
{
if (iLeft != 0) constraint.x -= Mathf.Lerp(limitWidth - finalWidth, 0f, piv.x);
else constraint.x += Mathf.Lerp(0f, limitWidth - finalWidth, piv.x);
finalWidth = limitWidth;
}
int limitHeight = finalHeight;
if (finalHeight < minHeight) limitHeight = minHeight;
else if (finalHeight > maxHeight) limitHeight = maxHeight;
if (finalHeight != limitHeight)
{
if (iBottom != 0) constraint.y -= Mathf.Lerp(limitHeight - finalHeight, 0f, piv.y);
else constraint.y += Mathf.Lerp(0f, limitHeight - finalHeight, piv.y);
finalHeight = limitHeight;
}
// Centered pivot requires power-of-two dimensions
if (piv.x == 0.5f) finalWidth = ((finalWidth >> 1) << 1);
if (piv.y == 0.5f) finalHeight = ((finalHeight >> 1) << 1);
// Update the position, width and height
Vector3 pos = t.localPosition + offset + rot * constraint;
t.localPosition = pos;
w.SetDimensions(finalWidth, finalHeight);
// If the widget is anchored, we should update the anchors as well
if (w.isAnchored)
{
t = t.parent;
float x = pos.x - piv.x * finalWidth;
float y = pos.y - piv.y * finalHeight;
if (w.leftAnchor.target) w.leftAnchor.SetHorizontal(t, x);
if (w.rightAnchor.target) w.rightAnchor.SetHorizontal(t, x + finalWidth);
if (w.bottomAnchor.target) w.bottomAnchor.SetVertical(t, y);
if (w.topAnchor.target) w.topAnchor.SetVertical(t, y + finalHeight);
}