Unity3D坐标与UI坐标转化差别过大

在UI Canvas的Render Mode模式是Screen Space-Camera模式极其容易3D坐标值转UI坐标出错。
**具体原因是:**Canvas的Rect Transform锁定,其Scale的倍数值不是1,所以导致从3D的坐标数值转换成UI坐标时就会出现问题。
正确做法:

      1、 声明变量: 3D物体、 UI的RectTransform、 Canvas的RectTransform、 Canvas所使用的Camera2、将物体的世界坐标转换为Canvas内的局部坐标3、设置UI元素的位置为Canvas内的局部坐标

代码:

public class TitileMove : MonoBehaviour
{// 3D物体public Transform object3D;// UI Image的RectTransformpublic RectTransform uiImageRectTransform;// Canvas的RectTransformpublic RectTransform canvasRectTransform;// Canvas所使用的Camerapublic Camera canvasCamera;public GameObject lastSelectedObject;private bool isDragging = false;private bool isRotating = false;private Vector3 lastMousePosition;private void OnBecameInvisible(){// 当物体不可见时,隐藏UI元素uiImageRectTransform.gameObject.SetActive(false);}void Update(){// 如果鼠标左键按下if (Input.GetMouseButtonDown(0)){Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);RaycastHit hit;// 射线检测是否点击到物体if (Physics.Raycast(ray, out hit)){GameObject selectedObject = hit.collider.gameObject;// 判断是否点击到了我们想要拖拽的物体if (selectedObject.transform.name == "3"){uiImageRectTransform.gameObject.SetActive(true);// 开始拖拽// 将物体的世界坐标转换为Canvas内的局部坐标Vector2 localPos;RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTransform, Camera.main.WorldToScreenPoint(selectedObject.transform.position), canvasCamera, out localPos);// 设置UI元素的位置为Canvas内的局部坐标localPos = new Vector2(localPos.x - 249, localPos.y + 70);uiImageRectTransform.localPosition = localPos;lastSelectedObject = selectedObject;Vector3 objectPosition = selectedObject.transform.position;lastMousePosition = Input.mousePosition;}else{// 隐藏UI元素uiImageRectTransform.gameObject.SetActive(false);}}isRotating = true;// 检测物体是否不可见并隐藏UI元素if (lastSelectedObject != null && IsObjectInvisible(lastSelectedObject)){uiImageRectTransform.gameObject.SetActive(false);}}if (isRotating && object3D != null){// 获取当前鼠标位置和上一帧鼠标位置之间的差值Vector3 deltaMouse = Input.mousePosition - lastMousePosition;// 根据差值来计算旋转角度float rotationSpeed = 0.25f; // 调整旋转速度float rotationY = deltaMouse.x * rotationSpeed;// 应用旋转object3D.transform.Rotate(Vector3.up, -rotationY, Space.World);// 更新上一帧鼠标位置lastMousePosition = Input.mousePosition;if (uiImageRectTransform != null){//  uiImageRectTransform.GetComponent<RectTransform>().anchoredPosition = new Vector2(uiImageRectTransform.GetComponent<RectTransform>().anchoredPosition.x + deltaMouse.x, uiImageRectTransform.GetComponent<RectTransform>().anchoredPosition.y);// 将物体的世界坐标转换为屏幕坐标Vector2 screenPos = RectTransformUtility.WorldToScreenPoint(null, uiImageRectTransform.position);// 将屏幕坐标转换为Canvas内的局部坐标RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTransform, screenPos, null, out Vector2 localPos);localPos = new Vector2(localPos.x + deltaMouse.x, localPos.y);// 设置物体的局部坐标uiImageRectTransform.anchoredPosition = localPos;}}// 如果鼠标左键释放if (Input.GetMouseButtonUp(0)){isRotating = false;}}// 检测物体是否不可见private bool IsObjectInvisible(GameObject obj){// 获取物体的包围盒Bounds bounds = obj.GetComponent<Renderer>().bounds;// 获取摄像机的视锥体平面Plane[] frustumPlanes = GeometryUtility.CalculateFrustumPlanes(Camera.main);// 检查包围盒是否与视锥体相交return !GeometryUtility.TestPlanesAABB(frustumPlanes, bounds);}// 检测物体是否被遮挡private bool IsObjectOccluded(GameObject obj){// 获取摄像机到物体的方向Vector3 directionToTarget = obj.transform.position - Camera.main.transform.position;// 发射射线Ray ray = new Ray(Camera.main.transform.position, directionToTarget);RaycastHit hit;// 射线检测是否有其他碰撞器位于射线路径上if (Physics.Raycast(ray, out hit, directionToTarget.magnitude)){// 如果射线击中的物体不是目标物体,则表示目标物体被遮挡if (hit.collider.gameObject != obj){return true;}}return false;}
}

重点

// 将物体的世界坐标转换为Canvas内的局部坐标Vector2 localPos;RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTransform, Camera.main.WorldToScreenPoint(selectedObject.transform.position), canvasCamera, out localPos);// 设置UI元素的位置为Canvas内的局部坐标localPos = new Vector2(localPos.x - 249, localPos.y + 70);uiImageRectTransform.localPosition = localPos;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/19791.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT 是如何工作的:从预训练到 RLHF

欢迎来到人工智能的未来:生成式人工智能!您是否想知道机器如何学习理解人类语言并做出相应的反应?让我们来看看ChatGPT ——OpenAI 开发的革命性语言模型。凭借其突破性的 GPT-3.5 架构,ChatGPT 席卷了世界,改变了我们与机器通信的方式,并为人机交互开辟了无限可能。随着…

改进的智能优化算法定性分析:种群多样性分析(Analysis of the population diversity)

目录 一、智能优化算法改进种群多样性分析 二、GWO与IGWO种群多样性对比 三、GWO与改进的GWO1种群多样性分析 四、代码获取 一、智能优化算法改进种群多样性分析 为了验证所提出的IDMO中种群多样性的丰富性&#xff0c;我们使用下式计算本节中的种群多样性。这个式…

Java并发系列之四:重中之重AQS

上一期我们介绍了乐观锁&#xff0c;而乐观锁的本质即是CAS&#xff0c;操作系统提供了支持CAS修改内存值的原子指令&#xff0c;所以乐观锁得以实现。从软件工程的角度去看&#xff0c;虽然底层已经通过CAS实现了乐观锁&#xff0c;Java的底层已经在Unsafe这个类中封装了compa…

【BASH】回顾与知识点梳理(三)

【BASH】回顾与知识点梳理 三 三. 命令别名与历史命令3.1 命令别名设定&#xff1a; alias, unalias3.2 历史命令&#xff1a;history同一账号同时多次登入的 history 写入问题无法记录时间 三. 命令别名与历史命令 我们知道在早期的 DOS 年代&#xff0c;清除屏幕上的信息可以…

《Java极简设计模式》第02章:抽象工厂模式(AbstractFactoty)

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 源码地址&#xff1a;https://github.com/binghe001/java-simple-design-patterns/tree/master/j…

3.病人排队

【题目】 病人登记看病&#xff0c;编写一个程序&#xff0c;将登记的病人按照以下原则排出看病的先后顺序&#xff1a; 老年人&#xff08;年龄 > 60岁&#xff09;比非老年人优先看病。 老年人按年龄从大到小的顺序看病&#xff0c;年龄相同的按登记的先后顺序排序。 非…

Cirno‘s Perfect Equation Class 2023牛客暑期多校训练营5 D

登录—专业IT笔试面试备考平台_牛客网 题目大意&#xff1a;有q次询问&#xff0c;每次给出三个整数k&#xff0c;c&#xff0c;n&#xff0c;求有多少满足条件的数对&#xff08;a&#xff0c;b&#xff09;满足kabc且c是b的倍数&#xff0c;且gcd(a,b)>n 1<q<100;…

Redis实现延时队列

缓存队列延时向接口报工&#xff0c;并支持多实例部署。 引入依赖 <dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-data</artifactId><version>3.17.4</version> </dependency> 注入RedisClient …

flask中实现restful-api

flask中实现restful-api 举例&#xff0c;我们可以创建一个用于管理任务&#xff08;Task&#xff09;的API。在这个例子中&#xff0c;我们将有以下API&#xff1a; GET /tasks: 获取所有任务POST /tasks: 创建一个新的任务GET /tasks/<id>: 获取一个任务的详情PUT /t…

prometheus+grafana进行服务器资源监控

在性能测试中&#xff0c;服务器资源是值得关注一项内容&#xff0c;目前&#xff0c;市面上已经有很多的服务器资 源监控方法和各种不同的监控工具&#xff0c;方便在各个项目中使用。 但是&#xff0c;在性能测试中&#xff0c;究竟哪些指标值得被关注呢&#xff1f; 监控有…

c++ | const 对常量的绑定

这一块&#xff0c;感觉很真的不好描述。最好就是搬着primer去啃去理解了。 const 核心思想&#xff0c;就是const对象很多操作都被限制了。类型决定对象操作 const 常量引用&#xff0c;所引用的对象必须是确定的&#xff08;粗俗的讲就是字面值 常量&#xff09; const int …

appium自动爬取数据

爬取类容&#xff1a;推荐知识点中所有的题目 爬取方式&#xff1a;appium模拟操作获取前端数据 入门级简单实现&#xff0c;针对题目和答案是文字内容的没有提取出来 适用场景;数据不多&#xff0c;参数加密&#xff0c;反爬严格等场景 from appium import webdriver impor…

git 常用命令有哪些

Git 是我们开发工作中使用频率极高的工具&#xff0c;下面总结下他的基本指令有哪些&#xff0c;顺便温习一下。 前言 一般项目中长存2个分支&#xff1a; 主分支&#xff08;master&#xff09; 和开发分支&#xff08;develp&#xff09; 项目存在三种短期分支 &#xff1a…

Linux安装MySQL 8.1.0

MySQL是一个流行的开源关系型数据库管理系统&#xff0c;本教程将向您展示如何在Linux系统上安装MySQL 8.1.0版本。请按照以下步骤进行操作&#xff1a; 1. 下载MySQL安装包 首先&#xff0c;从MySQL官方网站或镜像站点下载MySQL 8.1.0的压缩包mysql-8.1.0-linux-glibc2.28-x…

k8s实战

一、pod 1. 配置文件 2.探针 【1】类型 StartupProde&#xff1a;启动探针&#xff0c;判断程序是否启动LivenessProbeReadlinessProbe&#xff1a; 确认应用是否启动成功 【2】探测方式 ExecAction&#xff1a;在容器内执行一个命令&#xff0c;如果返回值为0&#xff0…

快速WordPress个人博客并内网穿透发布到互联网

快速WordPress个人博客并内网穿透发布到互联网 文章目录 快速WordPress个人博客并内网穿透发布到互联网 我们能够通过cpolar完整的搭建起一个属于自己的网站&#xff0c;并且通过cpolar建立的数据隧道&#xff0c;从而让我们存放在本地电脑上的网站&#xff0c;能够为公众互联网…

[RK3568 Android11] 开发之默认授予系统预置的APP权限

[RK3568 Android11] 开发之默认授予系统预置的APP权限 [RK3568 Android11] 开发之默认授予系统预置的APP权限_rk3568 授予所有文件的管理权限_~未来可期~的博客-CSDN博客

分享 一个类似 ps 辅助线功能

效果图片&#xff1a; 提示&#xff1a;这里的样式我做边做了修改&#xff0c;根据个人情况而定。 //你也可以npm下载 $ npm install --save vue-ruler-tool特点 没有依赖可拖动的辅助线快捷键支持 开始使用 1. even.js /*** description 绑定事件 on(element, event, han…

通用商城项目(中)

金山编译器出问题了。下面段落标号全出问题了&#xff0c;排版也出问题了。懒得改了。 使用对象存储OSS&#xff0c;保存品牌logo 新建Module&#xff0c;提供上传、显示服务 有些不明所以的&#xff0c;按照steinliving-commodity配置了一通pom.xml 新建application.yml&…

【NLP概念源和流】 06-编码器-解码器模型(6/20 部分)

一、说明 在机器翻译等任务中,我们必须从一系列输入词映射到一系列输出词。读者必须注意,这与“序列标记”不同,在“序列标记”中,该任务是将序列中的每个单词映射到预定义的类,如词性或命名实体任务。 作者生成 在上面的