空间划分算法优化碰撞检测研究(网格划分、四叉树\八叉树、层次包围盒树BVH)Unity C#实现

本文探讨了在碰撞检测中如何使用空间划分算法提高效率,从暴力法开始,逐步介绍了网格划分、四叉树、松散四叉树和AABB树等方法。每种方法通过实测数据对比了其性能和适用场景,揭示了在不同空间和对象分布情况下,如何选择合适的空间划分策略以达到最佳优化效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

前言

一、Demo说明

二、暴力法

 三、网格划分

实测

分析

四、四叉树

四叉树的构建细节

 实测

五、松散四叉树

实测

八叉树

六、层次包围盒树(BVH)

包围盒

AABB树

AABB树构建细节

实测

总结

 


前言

碰撞检测是一个非常经典的问题。虽然现在我们都有物理引擎提供的便捷接口,很多时候不需要我们手动实现,但是了解其中的算法思想有助于拓展我们的思维。而且很多问题其实都可以转化为碰撞检测问题,如:视锥体裁剪、LOD(视野范围与显示对象的碰撞)、RTS游戏中单位自动攻击警戒范围内的敌方单位(警戒范围与敌方单位的碰撞)、光线追踪等。 本次分享的不是碰撞检测中的检测算法(分离轴、GJK等),而是用于过滤检测对象的空间划分算法。我将通过实现一个碰撞检测的小demo来介绍碰撞检测中如何使用空间划分做优化以及他们的实现原理。


一、Demo说明

在一个100*100的空间内,随机生成2000个1*1的小方块,小方块生成后会随机赋予一个初速度,小方块将沿速度方向匀速运动,碰到空间边界会反弹。小方块之间不会反弹。现在需要检查方块是否与其他方块发生了碰撞(相交),是的话将方块标记为红色,否则为白色。 每种方法的测试中都将列出以下数据做为对比:帧率(FPS)、维护空间数据结构耗时(rebuild time)、碰撞检测耗时(check time)、碰撞检测函数调用次数(intersectsCheckCount)。

使用trigger

使用Physics.OverlapBoxNonAlloc


二、暴力法

如果我们直接对所有的方块两两检测是否发生碰撞,那么算法的时间复杂度将是N平方。在测试中的2000个方块已经卡成PPT,不足1帧。

暴力法效果图


 三、网格划分

可以发现在暴力法中做了太多多余的检查,如果能提前过滤掉一些明显不可能发生碰撞的方块就好了。 思路:将空间按网格分块,只对有可能发生碰撞的网格内的方块进行碰撞检测。具体做法就开启一个网格的数组,然后根据方块的坐标计算出应该属于哪些格子,最后只需要对每个格子内的方块进行碰撞检测即可。

实测

下面是将使用32*32的网格来划分空间,这里可以通过对方块的左下角和右上角坐标取模快速得到方块属于哪些网格。经过网格划分之后性能得到了大幅提升。

 

网格划分效果图

分析

网格划分在大部分时候都是简单又有效的。但是缺点也很明显,如果我们的空间再大点,方块分布也不是这么均匀的话。我们的网格大小就不好定了。网格太大的话碰撞检测的候选项就会增多,降低优化效果。网格太小的话就需要开辟更多的网格节点,而且可能很多节点都不会包含方块造成内存的浪费。下面是将空间扩大到1000*1000,方块初始位置设为左下角后的测试。

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值