检测射线与边界盒AABB相交(C#代码Unity环境下测试通过)

本文详细解释了在Unity中使用Bounds.IntersectRay方法进行碰撞检测的算法,并指出有优化空间,建议根据实际场景进行调整。

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

        说明:如果仅仅是再Unity环境下使用的话,直接使用Bounds.IntersectRay方法就好了,这里仅仅探索其算法。

        上代码:

bool RayCrossBounds(Ray ray, Bounds bounds)
{
	if (bounds.Contains(ray.origin)) return true;
	//
	float tMinX = float.MinValue;
	float tMaxX = float.MaxValue;
	if (Mathf.Approximately(ray.direction.x, 0))
	{
		if (ray.origin.x <= bounds.min.x || ray.origin.x >= bounds.max.x) return false;
	}
	else
	{
		tMinX = (bounds.min.x - ray.origin.x) / ray.direction.x;
		if (tMinX < 0) tMinX = 0;
		tMaxX = (bounds.max.x - ray.origin.x) / ray.direction.x;
		if (tMaxX < 0) tMaxX = 0;
		if (tMinX < 0 && tMaxX < 0) return false;
	}

	if (tMinX > tMaxX)
	{
		float temp = tMinX;
		tMinX = tMaxX;
		tMaxX = temp;
	}
	//
	float tMinY = float.MinValue;
	float tMaxY = float.MaxValue;
	if (Mathf.Approximately(ray.direction.y, 0))
	{
		if (ray.origin.y <= bounds.min.y || ray.origin.y >= bounds.max.y) return false;
	}
	else
	{
		tMinY = (bounds.min.y - ray.origin.y) / ray.direction.y;
		if (tMinY < 0) tMinY = 0;
		tMaxY = (bounds.max.y - ray.origin.y) / ray.direction.y;
		if (tMaxY < 0) tMaxY = 0;
		if (tMinY < 0 && tMaxY < 0) return false;
	}

	if (tMinY > tMaxY)
	{
		float temp = tMinY;
		tMinY = tMaxY;
		tMaxY = temp;
	}
	//
	float tMinZ = float.MinValue;
	float tMaxZ = float.MaxValue;
	if (Mathf.Approximately(ray.direction.z, 0))
	{
		if (ray.origin.z <= bounds.min.z || ray.origin.z >= bounds.max.z) return false;
	}
	else
	{
		tMinZ = (bounds.min.z - ray.origin.z) / ray.direction.z;
		if (tMinZ < 0) tMinZ = 0;
		tMaxZ = (bounds.max.z - ray.origin.z) / ray.direction.z;
		if (tMaxZ < 0) tMaxZ = 0;
		if (tMinZ < 0 && tMaxZ < 0) return false;
	}

	if (tMinZ > tMaxZ)
	{
		float temp = tMinZ;
		tMinZ = tMaxZ;
		tMaxZ = temp;
	}
	//Get Max min value
	float tMin = tMinX;
	if (tMin < tMinY) tMin = tMinY;
	if (tMin < tMinZ) tMin = tMinZ;
	//Get Min max value
	float tMax = tMaxX;
	if (tMax > tMaxY) tMax = tMaxY;
	if (tMax > tMaxZ) tMax = tMaxZ;

	if (tMax < tMin) return false;

	return true;
}

        该算法应该还有很多优化的余地,使用前应该考虑根据实际情况优化。

原理参考链接

### 在 Unity 中实现部分网格的选择与编辑 在 Unity 编辑器环境中,对于复杂模型的部分网格选择和编辑功能可以通过自定义脚本或插件来完成。通常情况下,Unity 的标准工作流程并不直接支持对单个对象内部多个子网格的精细选择操作,但通过特定技术手段能够达成这一目标。 #### 实现思路概述 为了实现在场景视图中框选并高亮显示所选中的网格片段,需要编写一段 C# 脚本来处理鼠标事件以及碰撞检测逻辑: - **捕捉用户输入**:监听用户的鼠标按下、移动及释放动作,以此判断是否正在进行框选操作。 - **射线投射与边界测试**:当检测到有效的框选区域时,在该区域内发射多条射线并与目标模型的所有三角形面片进行相交测试;或者利用包围球/轴向对齐边界(AABB)快速筛选可能符合条件的对象集合[^1]。 ```csharp using UnityEngine; public class MeshSelection : MonoBehaviour { private void Update() { if (Input.GetMouseButtonDown(0)) { /* 开始框选 */ } if (Input.GetMouseButtonUp(0)) { /* 结束框选 */ } Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { // 对命中结果进一步分析... } } } ``` - **视觉反馈机制**:一旦确定哪些顶点属于当前选定范围,则可通过改变其颜色属性给予直观提示。这一步骤涉及到修改MeshRenderer材料参数或是动态生成新的带有透明度变化效果的材质实例用于临时覆盖原物体表面[^2]. 针对具体的应用场景——即希望像对待独立游戏物件那样单独操控这些局部几何结构,建议考虑如下方案之一: ##### 方案一:拆分原始资源文件 提前将大型静态模型分割成若干较小单元保存为预制体Prefab形式,这样不仅便于管理也利于后期维护更新。每个预制体内含有一组关联紧密且相对完整的形状特征作为基本构成要素。 ##### 方案二:运行时期间即时切割算法 采用程序化方式实时计算出待分离出来的子集,并将其转换为可交互的新实体加入至Hierarchy列表当中。此过程往往依赖于第三方库的帮助比如ProBuilder这类官方提供的建模扩展工具包[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值