unity UGUI跟随3D对象(基于Canvas渲染模式为ScreenSpace_camera)

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缩放的影响,处理很简单就是将之前修正的屏幕坐标除以画质的缩放就好了。

第一次写文章经验不足,也很懒,没有图片佐证,代码也没有贴。如有说明错误,希望各位读者阔以说明一哈,感谢指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity中,可以通过以下步骤在世界坐标系中使用射线点击Canvas渲染模式为Screen space-Camera的UI: 1. 创建一个摄像机,将其设置为Canvas渲染摄像机。 2. 将Canvas渲染模式设置为Screen space-Camera,并将其渲染摄像机设置为步骤1中创建的摄像机。 3. 在需要进行射线点击的对象上添加Collider组件,如Box Collider或Sphere Collider等。 4. 使用Camera.ScreenPointToRay()方法获取从摄像机发出的射线,并使用Physics.Raycast()方法检测射线是否与Collider相交。 5. 如果射线与Collider相交,则可以在代码中执行所需的操作,例如触发UI的点击事件。 以下是示例代码: ``` public class RaycastUI : MonoBehaviour { public Camera camera; void Update() { if (Input.GetMouseButtonDown(0)) { Ray ray = camera.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { if (hit.collider.gameObject.GetComponent<Button>()) { //执行按钮点击事件 hit.collider.gameObject.GetComponent<Button>().onClick.Invoke(); } } } } } ``` 在这个例子中,我们创建了一个名为RaycastUI的脚本,并将其挂载在摄像机上。在Update()方法中,我们使用GetMouseButtonDown(0)检测鼠标左键是否按下,并通过ScreenPointToRay()方法获取从摄像机发出的射线。然后使用Physics.Raycast()方法检测射线是否与Collider相交,如果相交并且该物体具有Button组件,则执行按钮的点击事件。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值