转化百分比_localPosition与anchoredPosition的转化关系

跳转至专题目录

专题推荐文章:

  1. 温故知新——RectTransform成员属性的再认识
  2. unity Scene View扩展之编辑器扩展总结
  3. Unity获取鼠标点击ui GameObject

本系列目录

  1. localPosition与anchoredPosition转化之瞎猫找死耗子
  2. localPosition与anchoredPosition转化
  3. 揭秘!anchoredPosition的几何意义!
  4. 证·RectTransform里的localPosition就是pivot的位置
  5. 温故知新——RectTransform成员属性的再认识✩✰✪✫✬✭✮✯★强烈推荐,个人力作!✩✰✪✫✬✭✮✯★

文中存在一些纰漏,更正之后的文档在

砂糖酱:温故知新——RectTransform成员属性的再认识​zhuanlan.zhihu.com

首先很感谢这篇文章,让我对RectTransform里面的各个属性有了很深了解,建议对RectTransform不是很了解的都可以读一下。

Unity进阶技巧 - RectTransform详解​www.jianshu.com
bf7c93ad24d62685c8577fd9e9eff26f.png

感谢完之后,进入我们的推理环节。

至于推理的起点,就是我们都熟知的事情,分别有以下6条:

       // offsetMin, offsetMax, sizeDelta, pivot, anchoredPosition 之间的关系
        public Vector2 offsetMin
        {
            get
            {
                return anchoredPosition - Vector2.Scale(sizeDelta, pivot);
            }
            set
            {
                Vector2 offset = value - (anchoredPosition - Vector2.Scale(sizeDelta, pivot));
                sizeDelta -= offset;
                anchoredPosition += Vector2.Scale(offset, Vector2.one - pivot);
            }
        }

        public Vector2 offsetMax
        {
            get
            {
                return anchoredPosition + Vector2.Scale(sizeDelta, Vector2.one - pivot);
            }
            set
            {
                Vector2 offset = value - (anchoredPosition + Vector2.Scale(sizeDelta, Vector2.one - pivot));
                sizeDelta += offset;
                anchoredPosition += Vector2.Scale(offset, pivot);
            }
        }
  1. offsetMin, offsetMax, sizeDelta, pivot, anchoredPosition 之间的关系(见上方代码,源于unity现在开源的代码中)(这个就是万恶之源的关系式
  2. sizeDelta=offsetMax - offsetMin(见上方链接文章中的五、sizeDelta详解)
  3. offsetMin = UI左下角坐标-anchorMin锚点坐标(见上方链接文章中的四、offsetMin和offsetMax详解)
  4. offsetMax= UI右上角坐标-anchorMax锚点坐标(见上方链接文章中的四、offsetMin和offsetMax详解)
  5. 除了上面链接提到的,和上面几条提到几个属性变量,RectTransform里面还有一个rect(Rect),存着这个UI的起点坐标、最大坐标、宽高(毕竟现在知道了sizeDelta并不是表示UI的真实大小了)
  6. pivot点就是我们UI的中心点,它的位置,就表示UI对象的位置;子节点的pivot,与父节点的pivot之间的坐标插值,就是当前UI的localPosition(我自己推理证明的,证明方法下一篇文章写吧)(用的就是这个,将localPosition和anchoredPosition联系在一起的

我们已经理清楚了RectTransform的各个属性变量的关系了,那么现在就反过来,从第6条开始,一步一步往第一条的关系式里面靠。

f41bf3106401d8dec3b80eb46049f656.png
白色为子节点,黑色为父节点

6100014ee8bf93be544e86600d108a25.png
子节点RectTransform

一、通过anchorMin和rect,求得锚点左下角锚点(AnchorMin)的坐标

1、anchorMin:表示锚点左下点在父节点位置的百分比,0-1之间

be0bc0f73c8ba9e070af93cb52ba92f8.png

2、由anchorMin的定义可以知道,要求出这个位置,就需要用到父节点的真实大小了,即parentRectTransform.rect

8358faefc1b10cd3fb4a76dc774236ce.png
为了方便表示,将AnchorMin改为(0.1f, 0.1f)

3、根据定义,求得偏移量为 offset = Vector2.Scale(rect.anchorMin, parentRect.rect.size); // 父节点的长宽 * anchorMin这个百分比。

4、最后, 将这个偏移量加上parentRect.min这个坐标,即可以得到左下角锚点AnchorMin的坐标(在父节点坐标系中)

Vector2 anchorMinPos = parentRect.rect.min + Vector2.Scale(rect.anchorMin, parentRect.rect.size);

5、右上角锚点AnchorMax同理(有兴趣的可以自己证明):

 Vector2 anchorMaxPos = parentRect.rect.max - Vector2.Scale(Vector2.one - rect.anchorMax, parentRect.rect.size);

二、通过rect和localPosition,求出当前节点左下角位置

dae02347f8f4eda1ea16cddbbb410030.png

1、众所周知,Rect里面有一个min,可以表示左下角的坐标(这个坐标的坐标系为当前UI gameObject的)

2、这时候我们会发现,求出来的左下角锚点与UI左下角的坐标系不一样,需要进行坐标系转化

3、理所当然的,子节点坐标系转父节点坐标系简单一点,只需要在子节点坐标系下加一个localPosition,即可转换,所以我们求出来左下角坐标为:

Vector2 rectMinPos = rect.rect.min + localPosition2D;

4、右上角坐标同理:

Vector2 rectMaxPos = rect.rect.max + localPosition2D;

三、需要推理计算的步骤已经完了,剩下的就代公式就好了

// 1、求offsetMin, offsetMax:
Vector2 offsetMin = rectMinPos - anchorMinPos;
Vector2 offsetMax = rectMaxPos - anchorMaxPos;

// 2、求sizeDelta 
 Vector2 sizeDelta = offsetMax - offsetMin;

// 3、通过offsetMin 求anchoredPosition (最后一步啦)
Vector2 anchoredPositionByMin = offsetMin + Vector2.Scale(sizeDelta, rect.pivot); 

// 4、因为从源码里面可以看到,除了offsetMin ,offsetMax也可以求出anchoredPosition (这两个2选1就好了)
Vector2  anchoredPositionByMax = offsetMax - Vector2.Scale(sizeDelta, Vector2.one - pivot);

四、总结

然后将上面所有流程统一起来,就可以得到下面代码啦

     RectTransform rect = GetComponent<RectTransform>();
     RectTransform parentRect = transform.parent.GetComponent<RectTransform>();

     Vector2 GetAnchoredPositionByLocalPosition()
    {
        // 通过OffsetMin、OffsetMax,将anchoredPosition和localPosition联系起来
        Vector2 localPosition2D = new Vector2(rect.localPosition.x, rect.localPosition.y);

        Vector2 anchorMinPos = parentRect.rect.min + Vector2.Scale(rect.anchorMin, parentRect.rect.size);
        Vector2 rectMinPos = rect.rect.min + localPosition2D;
        Vector2 offsetMin = rectMinPos - anchorMinPos;

        Vector2 anchorMaxPos = parentRect.rect.max - Vector2.Scale(Vector2.one - rect.anchorMax, parentRect.rect.size);
        Vector2 rectMaxPos = rect.rect.max + localPosition2D;
        Vector2 offsetMax = rectMaxPos - anchorMaxPos;

        Vector2 sizeDelta = offsetMax - offsetMin;

        Vector2 anchoredPosition = offsetMin + Vector2.Scale(sizeDelta, rect.pivot); 

        return anchoredPosition;
    }

五、后记

我们这篇文章只是了解一下localPosition和anchoredPosition之间的转化关系,毕竟疑惑了我好久的一个问题,网上也一直没找到答案,于是就自己动手去了解、推理、计算了。

不过当小数点过多的时候,最后几位会有误差,毕竟感觉可能unity底层与c#层的计算精度可能有区别,个人就认为允许范围内了。

2e01d36db136e8f11b0d612595906f97.png
见GetAnchoredPosition组件,上面为直接拿到的数据,下面为计算出来的数据

当然我们实际开发过程中并不需要调用这么一个函数进行转化,直接rect.localPostion就能拿到localPosition,rect.anchroedPostion就能拿到anchroedPostion~~

再次感谢并推荐这篇文章,帮助真的很大,有种茅塞顿开的感觉

Unity进阶技巧 - RectTransform详解​www.jianshu.com
bf7c93ad24d62685c8577fd9e9eff26f.png

后再推荐一下我做这个的github工程

https://github.com/Zhunity/Position​github.com

PS:

毕竟是我个人自己逆推出来的,没有测试到所有情况,如果发现错误的同学,也希望指出来让我再推理一下~~~


感谢看完,文中存在一些纰漏,更正之后的文档在

砂糖酱:温故知新——RectTransform成员属性的再认识​zhuanlan.zhihu.com
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值