Unity包围盒

本文介绍了在Unity中如何获取和更新Mesh与Renderer的包围盒信息,包括Mesh.bounds和Renderer.bounds的差异,以及如何在Update()函数中实时获取包围盒的变化。

比如,目前导入了一个obj文件,想知道它的AABB包围盒是什么。

官方文档

Unity - Scripting API: Bounds (unity3d.com)

可以看到,包围盒有三个类别的:

Mesh.bounds

Unity - Scripting API: Mesh.bounds (unity3d.com)

不随gameobject的几何变换而变换,大概是直接用obj里的顶点坐标算出来的;也就是所谓的模型坐标系。

api怎么调用的?主要就是这几句:

试一试

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BoundTest : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Mesh mesh = GetComponent<MeshFilter>().mesh;
        Bounds bounds = mesh.bounds;
        print(bounds.center); // 把文档里的属性,都打印出来看看
        print(bounds.size);
        print(bounds.min);
        print(bounds.max);
        print(bounds.extents);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

关于文档里面not change的演示:

代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BoundTest : MonoBehaviour
{
    private Mesh mesh;
    private Bounds bounds;

    // Start is called before the first frame update
    void Start()
    {

        mesh = GetComponent<MeshFilter>().mesh;
        // bounds = mesh.bounds; // 不能放到这里的,放在这里的话,每帧打印的都是同一个bounds;就算是rend.bounds,打印结果也不变
    }

    // Update is called once per frame
    void Update()
    {
        bounds = mesh.bounds; // 应该实时获取
        print(bounds.center);
    }
}

结果: 

Render.bounds

Unity - Scripting API: Renderer.bounds (unity3d.com)

主要是这么几句:

试一试

代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BoundTest : MonoBehaviour
{
    private Mesh mesh;
    private Renderer rend;

    private Bounds bounds;

    // Start is called before the first frame update
    void Start()
    {
        mesh = GetComponent<MeshFilter>().mesh;
        rend = GetComponent<Renderer>();
    }

    // Update is called once per frame
    void Update()
    {
        //bounds = mesh.bounds;
        bounds = rend.bounds; // 实时获取包围盒,才能看到变没变

        print(bounds.center);
    }
}

后记

知道这些,其实就差不多了。

更详细的可以看这些:

(87条消息) Unity Bounds的理解_一梭键盘任平生的博客-优快云博客

(87条消息) 【Unity3D】绘制物体外框线条盒子_unity 绘制线框_little_fat_sheep的博客-优快云博客

总结的很好的:

### 实现层次包围盒Unity 中实现层次包围盒 (Hierarchical Bounding Box),可以显著提高大规模场景中的碰撞检测和视锥体剔除效率。为了构建有效的层次包围盒,通常采用树形结构来组织物体及其对应的边界框。 #### 构建层次包围盒的基础概念 层次包围盒是一种递归定义的空间划分方法,其中每个节点代表一个较大的包围盒,其子节点则表示更细粒度的分割区域。这种结构允许快速排除远离观察者的对象群组,从而减少不必要的计算开销[^2]。 #### 创建基本的包围盒类 首先,在 Unity 中创建一个新的 C# 脚本来定义 `BoundingBox` 类: ```csharp using UnityEngine; public class BoundingBox { public Bounds bounds; // Constructor to initialize the bounding box with a GameObject's collider. public BoundingBox(Collider col){ this.bounds = new Bounds(col.bounds.center, col.bounds.size); } } ``` 此代码片段展示了如何基于给定的游戏对象生成初始的包围盒实例。 #### 组织成层次结构 接下来,扩展上述基础以支持多级嵌套: ```csharp using System.Collections.Generic; public class HierarchyNode : MonoBehaviour { private List<HierarchyNode> childrenNodes; public BoundingBox nodeBox; void Start(){ childrenNodes = new List<HierarchyNode>(); // Initialize root or child nodes here... } /// <summary> /// Adds a game object as part of this hierarchy level and updates its bounding volume accordingly. /// </summary> public void AddChild(GameObject objToAdd){ var newNode = Instantiate(this.gameObject).GetComponent<HierarchyNode>(); newNode.transform.SetParent(transform); // Update local bounding box based on added objects' colliders. foreach(var col in objToAdd.GetComponents<Collider>()) { if(nodeBox == null) { nodeBox = new BoundingBox(col); } else { ExpandBoundsToInclude(col); } childrenNodes.Add(newNode); } } private void ExpandBoundsToInclude(Collider otherCol){ if(otherCol != null && nodeBox != null){ nodeBox.bounds.Encapsulate(otherCol.bounds); } } } ``` 这段脚本实现了将游戏对象加入到当前节点并更新相应级别的包围盒逻辑。 #### 应用于实际项目中 要使层次包围盒发挥作用,还需要考虑以下几个方面: - **初始化**:遍历整个场景并将所有相关联的对象分配至合适的层级位置。 - **维护**:每当有新对象被添加或现有对象发生位移时,及时调整所属分支以及整体尺寸。 - **查询优化**:设计高效的算法用于查找特定区域内存在的实体集合;例如,可以通过广度优先搜索(BFS) 或者深度优先搜索(DFS) 来定位目标范围内的叶子结点。 通过以上步骤可以在 Unity 里建立起功能完备且性能优越的层次包围盒体系,进而改善复杂环境下的交互体验与图形表现效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值