当前位置: 首页 > news >正文

【Unity3D中UI与物体可见性的判断方法】

系列文章目录

unity知识点


文章目录

  • 系列文章目录
  • 👉前言
  • 👉一、判断UI的可见性
    • 1-1、第一种
    • 1-2、通过RectTransform计算可视区域
    • 1-3、滚动容器内可见性检测(Scroll View)
  • 👉二、判断物体的可见性
    • 2-1、视锥体检测方法
    • 2-2、遮挡检测(射线检测法)
    • 2-3、使用渲染器回调(自动触发)
    • 2-4、判断物体中心点的可见性
    • 2-5、判断物体包围盒是否在Camera包围盒内
    • 2-6、完整方法
  • 👉壁纸分享
  • 👉总结


👉前言

在Unity中,判断UI和3D物体的可见性需要结合渲染逻辑、空间坐标系转换及特定API的使用

博客将会介绍Unity3D中UI与物体可见性的判断方法。
希望这篇博客对Unity的开发者有所帮助。
大家好,我是心疼你的一切,不定时更新Unity开发技巧,觉得有用记得一键三连哦。
欢迎点赞评论哦.下面就让我们进入正文吧 !


提示:以下是本篇文章正文内容,下面案例可供参考

👉一、判断UI的可见性

1-1、第一种

该方法适用于3D Canvas(第三种模式), 和 2D且赋值了相机的Canvas。(第二种模式)
不适合2D没有赋值相机的Canvas(第一种模式)。

    /// <summary>
    /// 判断ui是否能被相机Camera可见
    /// </summary>
    public bool GetUIDisable(Camera cam, RectTransform ui)
    {
        bool value = true;

        Vector3 pos = cam.WorldToScreenPoint(ui.position);
        if (pos.z < 0 || pos.x < 0 || pos.x > Screen.width || pos.y < 0 || pos.y > Screen.height)
            value = false;

        return value;
    }

1-2、通过RectTransform计算可视区域

public static bool IsUIVisible(RectTransform rectTransform) {
    // 获取UI的屏幕范围
    Vector3[] corners = new Vector3[4];
    rectTransform.GetWorldCorners(corners);
    
    // 计算屏幕的有效区域(假设主Canvas覆盖整个屏幕)
    Rect screenRect = new Rect(0, 0, Screen.width, Screen.height);
    
    // 检查所有角是否在屏幕内
    foreach (Vector3 corner in corners) {
        if (!screenRect.Contains(corner)) {
            return false;
        }
    }
    return true;
}

1-3、滚动容器内可见性检测(Scroll View)

动态加载列表项:当UI元素进入ScrollRect可视区域时加载数据。
自动适配布局:隐藏屏幕外的UI元素以优化性能。

public bool IsVisibleInScrollView(ScrollRect scrollRect, RectTransform content) {
    // 获取ScrollRect的可视区域
    Rect viewportRect = scrollRect.viewport.rect;
    Bounds viewportBounds = new Bounds(
        scrollRect.viewport.position, 
        new Vector2(scrollRect.viewport.rect.width, scrollRect.viewport.rect.height)
    );
    
    // 转换目标UI的坐标到Viewport空间
    Vector3[] contentCorners = new Vector3[4];
    content.GetWorldCorners(contentCorners);
    Matrix4x4 viewportMatrix = scrollRect.viewport.worldToLocalMatrix;
    
    // 检查是否与Viewport重叠
    return RectTransformUtility.RectangleContainsScreenPoint(
        scrollRect.viewport, 
        content.position, 
        null // 可指定特定摄像机
    );
}

👉二、判断物体的可见性

3D物体的可见性取决于

  1. 摄像机视锥体(Frustum):物体是否在摄像机视野内。
  2. 渲染器状态:Renderer.isVisible 属性(自动更新)。
  3. 遮挡关系:物体是否被其他物体遮挡(需额外计算)。

2-1、视锥体检测方法

public bool IsInCameraView(Camera camera, GameObject obj) {
    // 获取物体的包围盒
    Bounds bounds = obj.GetComponent<Renderer>().bounds;
    // 创建视锥体平面
    Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
    // 检查包围盒是否在视锥体内
    return GeometryUtility.TestPlanesAABB(planes, bounds);
}

2-2、遮挡检测(射线检测法)

public bool IsOccluded(GameObject target, Camera camera) {
    Vector3 dir = target.transform.position - camera.transform.position;
    float distance = dir.magnitude;
    Ray ray = new Ray(camera.transform.position, dir.normalized);
    
    if (Physics.Raycast(ray, out RaycastHit hit, distance)) {
        return hit.collider.gameObject != target;
    }
    return false;
}

2-3、使用渲染器回调(自动触发)

自带API

void OnBecameVisible() {
    // 当物体进入任何摄像机视野时触发
}

void OnBecameInvisible() {
    // 当物体离开所有摄像机视野时触发
}

2-4、判断物体中心点的可见性

    public bool GetObjCenterDisable(Camera cam, Transform obj)
    {
        //转化为视角坐标
        Vector3 viewPos = cam.WorldToViewportPoint(obj.position);

        //  z<0代表在相机背后
        if (viewPos.z < 0)
            return false;

        //  距离farClipPlane太远,摄像机看不到了
        if (viewPos.z > cam.farClipPlane)
            return false;

        //  x,y取值在 0~1之外时代表在视角范围外
        if (viewPos.x < 0 || viewPos.y < 0 || viewPos.x > 1 || viewPos.y > 1)
            return false;

        return true;
    }

2-5、判断物体包围盒是否在Camera包围盒内

在范围内就可见,则反之

    /// <summary>
    /// 相机包围盒
    /// </summary>
    private Plane[] _mTempCameraPlanes = new Plane[6];

    private void Update()
    {
        //使用方法;
        print(GetBondsVisable(transform.position, GetComponent<BoxCollider>().size));
    }

    private void LateUpdate()
    {
        //调用Unity的API,获取相机包围盒
        GeometryUtility.CalculateFrustumPlanes(Camera.main, _mTempCameraPlanes);
    }

    /// <summary>
    /// 通过相机包围盒来判定物体是否在视野中。
    /// </summary>
    public bool GetBondsVisable(Vector3 center, Vector3 size)
    {
        Bounds bound = new Bounds(center, size); //这里的Size是半径
        return GeometryUtility.TestPlanesAABB(_mTempCameraPlanes, bound);
    }

2-6、完整方法

结合了2-1、2-2、示例如下:

// 综合判断3D物体是否可见(视锥体 + 遮挡)
public bool IsObjectVisible(GameObject obj, Camera mainCam) {
    if (!IsInCameraView(mainCam, obj)) return false;
    if (IsOccluded(obj, mainCam)) return false;
    return true;
}

请添加图片描述


👉壁纸分享

在这里插入图片描述

👉总结

本次总结的就是UI与物体可见性的判断方法, 有需要会继续增加功能
如能帮助到你,就帮忙点个赞吧,三连更好哦,谢谢
你的点赞就是对博主的支持,有问题记得留言评论哦!
不定时更新Unity开发技巧,觉得有用记得一键三连哦。么么哒!

相关文章:

  • CSS基础知识学习指南
  • C语言--求n以内的素数(质数)
  • 蓝桥杯真题-危险系数DF
  • L2-051 满树的遍历
  • Java的基本语法(1)
  • 彻底改变我 React 开发方式的组件模式
  • 三格电子上新款——欧姆龙 CJ/CP系列 PLC 串口转网口
  • for循环的优化方式、循环的种类、使用及平替方案。
  • LEARNING DYNAMICS OF LLM FINETUNING【论文阅读笔记】
  • 如何深入理解protobuf
  • 小型实验室数控机床-迷你型数控加工中心|CNC数控车床
  • 软考 中级软件设计师 考点知识点笔记总结 day11 文件管理 设备管理
  • 51电子表
  • AI 之 LLM(大语言模型)是如何生成文本的!
  • 力扣经典算法篇-11-除自身以外数组的乘积(总乘积求除法,左右乘积法)
  • 探索 C++ 中的 const 关键字
  • 美食推荐小程序
  • OpenFeign 的实现原理详解
  • 探索在视频深度伪造中的细微的表情变化或对特定面部特征的小改动检测方法
  • 使用numpy构建逻辑回归模型及训练流程
  • 做移动网站优化软/微信营销软件哪个好用
  • 众创空间网站建设方案/站长之家音效
  • 网页qq邮箱打不开/seo推广优化平台
  • 郑州做网站经开区/今日头条网页版入口
  • 手机建网站步骤软件/创建免费网站
  • 织梦网站怎么重新安装教程/seoapp推广