前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Unity ugui Anchor锚点自动适配画布中的相对位置

Unity ugui Anchor锚点自动适配画布中的相对位置

作者头像
汐夜koshio
发布2020-07-02 10:36:49
1.9K0
发布2020-07-02 10:36:49
举报
文章被收录于专栏:U3DU3D

本随笔参考了以下博客,在此基础上进行优化和改进:

https://blog.csdn.net/qq_39640124/article/details/88284191

ugui中的Anchor预设如下:

允许我们快速对齐父物体的一部分轴向顶点或边,但有时我们并不是要对齐这些,而是需要对齐特定位置的某个点,例如:

如上图,上面的作战结束之后的等级信息B它应该是对齐父物体面板的什么位置呢?

当然了,你可以简单的将它设置为对齐屏幕右侧中点或者右上,那么此时无论屏幕分辨率如何改变,它的锚点Pivot距离屏幕右边缘的距离都不变。

但如果出现一种极端例子,屏幕的宽度小到比预设的距离还小,那么B早就跑到屏幕左侧去了。

显然,这样的Anchor预设调整是不太精准的,在屏幕分辨率改变较大时,很多不同对齐方式的元素有极大几率出现位置偏移甚至重叠。

ugui除了通过自带的预设,也可以手动输入Anchor的最大值和最小值来调整,当最大值和最小值相同时,它对齐的是相对百分比的一个点:

例如上面的B字母的中点精准的对齐方式是,距离父物体画布宽的82.9%高72.7%左右的位置,这样无论父物体随着分辨率如何改变,B的相对位置都保持不变。

值得注意的是,为了保证无任何偏移的可能,需要保证anchoredPosition为零,也就是面板中Pos为零。

但很遗憾的是,Unity编辑器暂时还没有办法自动对齐Anchor到物体的锚点Pivot或边框,当然了你可以每次尝试手动拖动,但保证你马上就会有口区的感觉,而且总会差那么一点对不齐。

下面是自动对齐的编辑器脚本,在网上参考了之前网友写过的对齐边框的写法,但发现只要锚点Pivot不在物件中心就会自动移动物体位置,在这里进行了一些优化修正,并增加了另一种对齐模式:

代码语言:javascript
复制
 1 using UnityEngine;
 2 using UnityEditor;
 3 
 4 public class AnchorsAdapt
 5 {
 6     [MenuItem("Tools/AnchorsAdaptSize")]
 7     private static void SelectionMS()
 8     {
 9         GameObject[] gos = Selection.gameObjects;
10         for (int i = 0; i < gos.Length; i++)
11         {
12             if (gos[i].GetComponent<RectTransform>() == null)
13                 continue;
14             AdaptSize(gos[i]);
15         }
16     }
17 
18     [MenuItem("Tools/AnchorsAdaptPivot")]
19     private static void SelectionMP()
20     {
21         GameObject[] gos = Selection.gameObjects;
22         for (int i = 0; i < gos.Length; i++)
23         {
24             if (gos[i].GetComponent<RectTransform>() == null)
25                 continue;
26             AdaptPivot(gos[i]);
27         }
28     }
29 
30     private static void AdaptPivot(GameObject go)
31     {
32         //------获取rectTransform----
33         RectTransform partentRect = go.transform.parent.GetComponent<RectTransform>();
34         RectTransform localRect = go.GetComponent<RectTransform>();
35 
36         //位置信息
37         Vector3 partentPos = go.transform.parent.position;
38         Vector3 localPos = go.transform.position;
39 
40         float partentWidth = partentRect.rect.width;
41         float partentHeight = partentRect.rect.height;
42 
43         //---------位移差------
44         float offX = localPos.x - partentPos.x;
45         float offY = localPos.y - partentPos.y;
46 
47         float rateW = offX / partentWidth;
48         float rateH = offY / partentHeight;
49         var anchor = new Vector2(.5f + rateW, .5f + rateH);
50         localRect.SetRtAnchorSafe(anchor, anchor);
51     }
52 
53     private static void AdaptSize(GameObject go)
54     {
55         //位置信息
56         Vector3 partentPos = go.transform.parent.position;
57         Vector3 localPos = go.transform.position;
58         //------获取rectTransform----
59         RectTransform partentRect = go.transform.parent.GetComponent<RectTransform>();
60         RectTransform localRect = go.GetComponent<RectTransform>();
61 
62         float partentWidth = partentRect.rect.width;
63         float partentHeight = partentRect.rect.height;
64         float localWidth = localRect.rect.width * 0.5f;
65         float localHeight = localRect.rect.height * 0.5f;
66         //---------位移差------
67         float offX = localPos.x - partentPos.x;
68         float offY = localPos.y - partentPos.y;
69 
70         float rateW = offX / partentWidth;
71         float rateH = offY / partentHeight;
72         localRect.anchorMax = localRect.anchorMin = new Vector2(0.5f + rateW, 0.5f + rateH);
73         localRect.anchoredPosition = Vector2.zero;
74 
75         //大小偏移
76         partentHeight = partentHeight * 0.5f;
77         partentWidth = partentWidth * 0.5f;
78         float rateX = (localWidth / partentWidth) * 0.5f;
79         float rateY = (localHeight / partentHeight) * 0.5f;
80 
81         //锚点偏移值
82         var pivotOffX = localRect.pivot.x-.5f;
83         var pivotOffY = localRect.pivot.y-.5f;
84         var pivotOff = new Vector2(localWidth * pivotOffX / partentWidth, localHeight * pivotOffY / partentHeight);
85 
86         localRect.anchorMax = new Vector2(localRect.anchorMax.x + rateX, localRect.anchorMax.y + rateY) - pivotOff;
87         localRect.anchorMin = new Vector2(localRect.anchorMin.x - rateX, localRect.anchorMin.y - rateY) - pivotOff;
88         localRect.offsetMax = localRect.offsetMin = Vector2.zero;
89     }
90 }

此脚本为编辑器Editor脚本,需要放在Editor文件夹下才能生效。其中安全设置Anchor的拓展方法如下:

代码语言:javascript
复制
 1     public static void SetRtAnchorSafe(this RectTransform rt, Vector2 anchorMin, Vector2 anchorMax)
 2     {
 3         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)
 4             return;
 5 
 6         var lp = rt.localPosition;
 7         //注意不要直接用sizeDelta因为该值会随着anchor改变而改变
 8         var ls = new Vector2(rt.rect.width, rt.rect.height);
 9 
10         rt.anchorMin = anchorMin;
11         rt.anchorMax = anchorMax;
12 
13         //动态改变anchor后size和localPostion可能会发生变化需要重新设置
14         rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, ls.x);
15         rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, ls.y);
16         rt.localPosition = lp;
17     }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-06-30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档