系列文章目录
unity知识点
文章目录
👉前言
在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物体的可见性取决于:
- 摄像机视锥体(Frustum):物体是否在摄像机视野内。
- 渲染器状态:Renderer.isVisible 属性(自动更新)。
- 遮挡关系:物体是否被其他物体遮挡(需额外计算)。
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开发技巧,觉得有用记得一键三连哦。么么哒!