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

这篇具有很好参考价值的文章主要介绍了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所使用的Camera
      2、将物体的世界坐标转换为Canvas内的局部坐标
      3、设置UI元素的位置为Canvas内的局部坐标

代码:

public class TitileMove : MonoBehaviour
{
    // 3D物体
    public Transform object3D;

    // UI Image的RectTransform
    public RectTransform uiImageRectTransform;

    // Canvas的RectTransform
    public RectTransform canvasRectTransform;

    // Canvas所使用的Camera
    public 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;
    }
}

重点文章来源地址https://www.toymoban.com/news/detail-617693.html

// 将物体的世界坐标转换为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;

到了这里,关于Unity3D坐标与UI坐标转化差别过大的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Unity3D】UI Toolkit简介

            UI Toolkit 是一种基于 Web 技术的 GUI 框架,是为了解决 UGUI 效率问题而设计的新一代 UI 系统(UGUI 的介绍详见→UGUI概述)。与 UGUI 不同,UI Toolkit 没有采用 GameObject 的方式,而是参考了 Web 技术的 XML 和 CSS 方案。这意味着它只保存变化的数据,而不是整个界面状态,

    2024年02月10日
    浏览(58)
  • 【Unity3D小功能】Unity3D中实现UI擦除效果、刮刮卡功能

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 大家好,我是佛系工程师 ☆恬静的小魔龙☆ ,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 使用Unity3D实现UI的擦拭效果、刮刮卡功能的效果实现方式比较多,比如说用Shader、Texture渲染都是可以

    2024年02月04日
    浏览(224)
  • 【Unity3D】实现UI点击事件穿透

              注意:EventSystem.current.RaycastAll获取到的对象列表是能够接受事件的,假如你的按钮Button自己身上没有Image,而是Button的子物体有,那么你就要给这个子物体也加上标签Tag才能响应到。 如果ExecuteEvents.Execute不管用,可以试试ExecuteEvents.ExecuteHierarchy

    2024年02月04日
    浏览(49)
  • 使用Unity生成UI预制体 (Unity3D)

    在Unity中,预制体(Prefab)是一种非常有用的工具,用于生成可重复使用的UI元素。预制体使得UI的创建和管理变得更加简单和高效。在本文中,我们将详细介绍如何使用Unity生成UI预制体,并提供相应的源代码示例。 步骤1:创建UI元素 首先,我们需要创建UI元素,例如按钮、

    2024年02月05日
    浏览(57)
  • Unity3D学习之UI系统——GUI

    设置Screen Type和Center Type 最终实现效果: 3.1.1 GUI 共同点 3.1.2 文本控件 可以传图片 在unity中拖入图片 可以把Rect 设置成public 的变量,在控件中设置 文字和图片均显示 toolTip 获取当前选中的空间的附带信息 GUI Style 控制样式 3.1.3 按钮控件 必须要按下并抬起才算被点击 长按按钮

    2024年01月22日
    浏览(68)
  • 【Unity3D】UI Toolkit数据动态绑定

            本文将实现 cvs 表格数据与 UI Toolkit 元素的动态绑定。         如果读者对 UI Toolkit 不是太了解,可以参考以下内容。 UI Toolkit简介 UI Toolkit容器 UI Toolkit元素 UI Toolkit样式选择器 UI Toolkit自定义元素         本文完整资源见→UI Toolkit数据动态绑定。 2.1 UI 搭建

    2024年02月08日
    浏览(53)
  • 【Unity3D】UI Toolkit自定义元素

    1 前言         UI Toolkit 支持通过继承 VisualElement 实现自定义元素,便于通过脚本控制元素。另外,UI Toolkit 也支持将一个容器及其所有子元素作为一个模板,便于通过脚本复制模板。         如果读者对 UI Toolkit 不是太了解,可以参考以下内容。 UI Toolkit简介 UI Toolkit容器

    2024年02月09日
    浏览(50)
  • Unity3D学习之UI系统——UGUI

    3.2.1 Screen Space -Overlay 覆盖模式 3.2.2 Screen Space - Camera 摄像机模式 创建专门的摄像机渲染UI 并让主摄像机不渲染UI层 3.2.3 World Space 宽高 * 缩放系数 = UI界面大小 参考分辨率 图片格式要改为Sprite 恒定像素模式计算公式 会根据当前分辨率 和 参考分辨率的比率自动计算UI的缩放量

    2024年02月21日
    浏览(258)
  • 【Unity3D】UI Toolkit样式选择器

            UI Toolkit简介 中介绍了样式属性,UI Toolkit容器 和 UI Toolkit元素 中介绍了容器和元素,本文将介绍样式选择器(Selector),主要包含样式类选择器(Class Selector)、C# 类选择器(Type Selector)、名称选择器(Name Selector)、通用选择器(Universal Selector)、后代选择器

    2024年02月03日
    浏览(51)
  • Unity3D学习之UI系统——NGUI

    资源商店搜索 学习版自行搜索 导入即可 创建UI 创建NGUI后,挂载在UI Root 和其 子Camera的脚本 分辨率自适应模式的基础 3.1.1 分辨率概念 3.1.2 Root的作用 3.1.3 root脚本各组件 Minimun Height 和 Maximum Height 用于拖动窗口时,如果窗口变得很小了,UI不缩放的话,会挡住游戏,使用Flex

    2024年03月17日
    浏览(83)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包