Unity ugui Anchor锚点自动适配画布中的相对位置
本随笔参考了以下博客,在此基础上进行优化和改进:
https://www.geek-share.com/detail/2762920910.html
ugui中的Anchor预设如下:
允许我们快速对齐父物体的一部分轴向顶点或边,但有时我们并不是要对齐这些,而是需要对齐特定位置的某个点,例如:
如上图,上面的作战结束之后的等级信息B它应该是对齐父物体面板的什么位置呢?
当然了,你可以简单的将它设置为对齐屏幕右侧中点或者右上,那么此时无论屏幕分辨率如何改变,它的锚点Pivot距离屏幕右边缘的距离都不变。
但如果出现一种极端例子,屏幕的宽度小到比预设的距离还小,那么B早就跑到屏幕左侧去了。
显然,这样的Anchor预设调整是不太精准的,在屏幕分辨率改变较大时,很多不同对齐方式的元素有极大几率出现位置偏移甚至重叠。
ugui除了通过自带的预设,也可以手动输入Anchor的最大值和最小值来调整,当最大值和最小值相同时,它对齐的是相对百分比的一个点:
例如上面的B字母的中点精准的对齐方式是,距离父物体画布宽的82.9%高72.7%左右的位置,这样无论父物体随着分辨率如何改变,B的相对位置都保持不变。
值得注意的是,为了保证无任何偏移的可能,需要保证anchoredPosition为零,也就是面板中Pos为零。
但很遗憾的是,Unity编辑器暂时还没有办法自动对齐Anchor到物体的锚点Pivot或边框,当然了你可以每次尝试手动拖动,但保证你马上就会有口区的感觉,而且总会差那么一点对不齐。
下面是自动对齐的编辑器脚本,在网上参考了之前网友写过的对齐边框的写法,但发现只要锚点Pivot不在物件中心就会自动移动物体位置,在这里进行了一些优化修正,并增加了另一种对齐模式:
using UnityEngine; using UnityEditor; public class AnchorsAdapt { [MenuItem("Tools/AnchorsAdaptSize")] private static void SelectionMS() { GameObject[] gos = Selection.gameObjects; for (int i = 0; i < gos.Length; i++) { if (gos[i].GetComponent<RectTransform>() == null) continue; AdaptSize(gos[i]); } } [MenuItem("Tools/AnchorsAdaptPivot")] private static void SelectionMP() { GameObject[] gos = Selection.gameObjects; for (int i = 0; i < gos.Length; i++) { if (gos[i].GetComponent<RectTransform>() == null) continue; AdaptPivot(gos[i]); } } private static void AdaptPivot(GameObject go) { //------获取rectTransform---- RectTransform partentRect = go.transform.parent.GetComponent<RectTransform>(); RectTransform localRect = go.GetComponent<RectTransform>(); //位置信息 Vector3 partentPos = go.transform.parent.position; Vector3 localPos = go.transform.position; float partentWidth = partentRect.rect.width; float partentHeight = partentRect.rect.height; //---------位移差------ float offX = localPos.x - partentPos.x; float offY = localPos.y - partentPos.y; float rateW = offX / partentWidth; float rateH = offY / partentHeight; var anchor = new Vector2(.5f + rateW, .5f + rateH); localRect.SetRtAnchorSafe(anchor, anchor); } private static void AdaptSize(GameObject go) { //位置信息 Vector3 partentPos = go.transform.parent.position; Vector3 localPos = go.transform.position; //------获取rectTransform---- RectTransform partentRect = go.transform.parent.GetComponent<RectTransform>(); RectTransform localRect = go.GetComponent<RectTransform>(); float partentWidth = partentRect.rect.width; float partentHeight = partentRect.rect.height; float localWidth = localRect.rect.width * 0.5f; float localHeight = localRect.rect.height * 0.5f; //---------位移差------ float offX = localPos.x - partentPos.x; float offY = localPos.y - partentPos.y; float rateW = offX / partentWidth; float rateH = offY / partentHeight; localRect.anchorMax = localRect.anchorMin = new Vector2(0.5f + rateW, 0.5f + rateH); localRect.anchoredPosition = Vector2.zero; //大小偏移 partentHeight = partentHeight * 0.5f; partentWidth = partentWidth * 0.5f; float rateX = (localWidth / partentWidth) * 0.5f; float rateY = (localHeight / partentHeight) * 0.5f; //锚点偏移值 var pivotOffX = localRect.pivot.x-.5f; var pivotOffY = localRect.pivot.y-.5f; var pivotOff = new Vector2(localWidth * pivotOffX / partentWidth, localHeight * pivotOffY / partentHeight); localRect.anchorMax = new Vector2(localRect.anchorMax.x + rateX, localRect.anchorMax.y + rateY) - pivotOff; localRect.anchorMin = new Vector2(localRect.anchorMin.x - rateX, localRect.anchorMin.y - rateY) - pivotOff; localRect.offsetMax = localRect.offsetMin = Vector2.zero; } }
此脚本为编辑器Editor脚本,需要放在Editor文件夹下才能生效。其中安全设置Anchor的拓展方法如下:
public static void SetRtAnchorSafe(this RectTransform rt, Vector2 anchorMin, Vector2 anchorMax) { if (anchorMin.x < 0 || anchorMin.x > 1 || anchorMin.y < 0 || anchorMin.y > 1 || anchorMax.x < 0 || anchorMax.x > 1 || anchorMax.y < 0 || anchorMax.y > 1) return; var lp = rt.localPosition; //注意不要直接用sizeDelta因为该值会随着anchor改变而改变 var ls = new Vector2(rt.rect.width, rt.rect.height); rt.anchorMin = anchorMin; rt.anchorMax = anchorMax; //动态改变anchor后size和localPostion可能会发生变化需要重新设置 rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, ls.x); rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, ls.y); rt.localPosition = lp; }
- Unity笔记 UGUI (画布 锚点 事件 遮罩 )
- Unity物体跟随鼠标点的位置自动寻路
- unity中UGUI图片箭头指向鼠标位置
- UGUI——画布锚点发布
- unity获取ugui上鼠标位置
- UIView设置为自动适配屏幕时,当用户旋转设备的时候,会调用layoutSubviews方法,我们只需重写 这个方法,然后判断用户屏幕的方向。在调整每个空间的位置即可。
- unity_NGUI系统学习(七)_Anchor锚点的设置和使用技巧
- 白鹭引擎(egret)中锚点(anchoroffset)的位置体会
- Unity射线&自动寻路/右键点击某一点会使物体跟随至鼠标点击位置/计算目标物体距离鼠标点击位置的距离
- unity 网页 基于 UniWebView 做UGUI 适配
- unity 在UI中 点击画布 返回鼠标所在画布的位置
- Unity ugui屏幕适配与世界坐标到ugui屏幕坐标的转换
- unity,set ugui rectTransform anchor by script
- Unity中NGUI里ScrollView选中的item遮挡自动滚动到中间或者合适位置
- Unity UGUI锚点快速定位(自适应)
- UNITY之UGUI屏幕适配
- Unity中NGUI里ScrollView选中的item遮挡自动滚动到中间或者合适位置
- 【小松教你手游开发】【unity实用技能】NGUI 自动适配屏幕大小
- Unity之UGUI脚本自动生成
- 用代码来控制自定义的控件 自动适应横竖屏时的相对位置