unity UGUI跟随3D对象(基于Canvas渲染模式为ScreenSpace_camera)
背景介绍:最近项目里需要一个ui跟随3d对象的脚本工具,一开始我以为是个很简单的问题,最后实现起来还是碰到了一些坑,在这记录一下。
正文:先说一下我们项目关于场景和UI渲染分别使用不同相机渲染,场景的相机渲染结果输出到一张rt上,然后在UGUI上使用一张rawImage显示场景渲染的结果。UI上Canvas的渲染模式我们设置的是ScreenSpace_camera. Canvas的适配模式选择的是Match Wdith or Height,match值是1。Reference Resolution设置的1920*1080.实现的方案就是 将3D对象的世界坐标转换为屏幕坐标,然后利用RectTransformUtility.screenpointtolocalpointinrectangle得到UI坐标。最后将ui的anchoredposition设置为该UI坐标。
但是这其中有几个问题出现了,首先是将3d对象的世界坐标转换为屏幕坐标时,需要将得到的屏幕坐标第一次修正。修正的处理是screenpos.x * screen.weight/1920,screenpos.y * screen.height/1080。然后注意到,我们场景渲染的结果是在一张rt上的,是由ui相机最终渲染到屏幕上的,所以此时我们需要对屏幕坐标的x进行第二次修正,为什么不用对y进行修正呢,因为前面我们有说到我们的match值是1,所以y方向是基准,不需要处理(永远都是1080)。那么我们此时需要怎样对x进行修正呢,很简单,我们只需要得到canvas上recttransform的sizedelta.x就好了,然后处理就是1920/canvas.getcomponent().sizedelta.x.因此在不考虑其他情况下我们最终对屏幕坐标的修正就是x方向上screenpos.x * screen.weight/canvas.getcomponent().sizedelta.x。y方向上就是screenpos.y*screen.height/1080.之后的处理就是利用上述的方法得到ui坐标赋值给ui的anchoredposition就ok了。
上文提到了不考虑其他情况是因为我们自己项目在处理画质上是这样的,3d场景输出到rt时,用户可以手动控制画质效果,对应的操作就是将本来是canvas.getcomponent().sizedelta这个值是作为对应的rt宽高乘以每个等级画质的比例,例如高画质是0.8,中画质0.67这样。因此在考虑画质的情况下,需要对画质进行反向处理修正rt缩放的影响,处理很简单就是将之前修正的屏幕坐标除以画质的缩放就好了。
第一次写文章经验不足,也很懒,没有图片佐证,代码也没有贴。如有说明错误,希望各位读者阔以说明一哈,感谢指正。