Unity--物理系统(碰撞检测)

文章来源:
【唐老狮】Unity——物理系统(碰撞检测) - 哔哩哔哩 (bilibili.com)
发生碰撞、有物理效果、触发可穿透、不同阶段

一、碰撞检测

碰撞发生必要条件:2个都有碰撞器,1个有刚体

1.1 刚体组件

让物体有物理作用

刚体参数

在这里插入图片描述

Mass:对象的质量(默认为千克)

Drag:空气阻力
根据力移动对象时影响对象的空气阻力大小。0 表示没有空气阻力,无穷大使对象立即停止移动

Angular Drag:扭矩阻力
根据扭矩旋转对象时影响对象的空气阻力大小。0 表示没有空气阻力。请注意,如果直接将对象的 Angular Drag 属性设置为无穷大,无法使对象停止旋转。

Use Gravity:是否使用重力

Is Kinematic:
如果启用此选项,则对象将不会被物理引擎驱动,只能通过 (Transform) 对其进行操作。对于移动平台,或者如果要动画附加了 HingeJoint 的刚体,此属性将非常有用。

Interpolate:仅当在刚体运动中看到急动时才尝试使用提供的选项之一。

  • None:不应用插值。
  • Interpolate:根据前一帧的变换来平滑变换。
  • Extrapolate:根据下一帧的估计变换来平滑变换。

Collision Detection:用于防止快速移动的对象穿过其他对象而不检测碰撞。

  • Discrete
    对场景中的所有其他碰撞体使用离散碰撞检测。其他碰撞体在测试碰撞时会使用离散碰撞检测。用于正常碰撞(这是默认值)。
  • Continuous
    对动态碰撞体(具有刚体)使用离散碰撞检测,并对静态碰撞体(没有刚体)使用基于扫掠的连续碰撞检测。设置为_连续动态 (Continuous Dynamic) 的刚体将在测试与该刚体的碰撞时使用连续碰撞检测。其他刚体将使用离散碰撞检测。用于连续动态 (Continuous Dynamic) 检测需要碰撞的对象。(此属性对物理性能有很大影响,如果没有快速对象的碰撞问题,请将其保留为 Discrete 设置)
  • Continuous Dynamic
    对设置为连续 (Continuous)和连续动态 (Continuous Dynamic)碰撞的游戏对象使用基于扫掠的连续碰撞检测。还将对静态碰撞体(没有刚体)使用连续碰撞检测。对于所有其他碰撞体,使用离散碰撞检测。用于快速移动的对象。
  • Continuous Speculative
    对刚体和碰撞体使用推测性连续碰撞检测。这也是可以设置运动物体的唯一 CCD 模式。该方法通常比基于扫掠的连续碰撞检测的成本更低。

Constraints:冻结。对刚体运动的限制。

  • Freeze Position
    有选择地停止刚体沿世界 X、Y 和 Z 轴的移动。
  • Freeze Rotation
    有选择地停止刚体围绕局部 X、Y 和 Z 轴旋转。

1.2 碰撞器组件

常用:Box、Sphere、Capsule
不常用:Wheel 环状、车轮 、Mesh、Terrain 地形

车轮参数

![[Pasted image 20240710225151.png]]

Mass:车轮的质量

Radius:车轮的半径

Wheel Damping Rate:这是应用于车轮的阻尼值

Suspension Distance:车轮悬架的最大延伸距离(在局部空间中测量)。悬架始终向下延伸穿过局部 Y 轴。

Force App Point Distance:此参数定义车轮上的受力点。此距离应该是距车轮底部静止位置的距离(沿悬架行程方向),以米为单位。当 forceAppPointDistance = 0 时,受力点位于静止的车轮底部。较好的车辆会使受力点略低于车辆质心。

Suspension Spring:悬架尝试通过增加弹簧力和阻尼力来到达目标位置 (Target Position)

  • Spring
    弹簧力尝试到达目标位置。值越大,悬架达到目标位置就越快
  • Damper
    抑制悬架速度。值越大,悬架弹簧移动就越
  • Target Position
    悬架沿悬架距离 (Suspension Distance) 的静止距离。1 对应于完全展开的悬架,0 对应于完全压缩的悬架。默认值为 0.5,与常规汽车的悬架行为匹配。

Forward Friction:车轮向前滚动时轮胎摩擦的特性。

Sideways Friction:车轮侧向滚动时轮胎摩擦的特性。

  • Extremum Slip:曲线的极值点。
  • Extremum Value:曲线的极值点。
  • Asymptote Slip:曲线的渐近点。
  • Asymptote Value:曲线的渐近点。
  • Stiffness:
    Extremum Value 和 Asymptote Value 的乘数(默认值为 1)。改变摩擦力的刚度。将此值设置为零将完全禁用车轮的所有摩擦力。通常在运行时修改刚度以使用脚本来模拟各种地面材质。

注意:
不必通过转动或滚动 WheelCollider 对象来控制汽车;附加了 WheelCollider 的对象应始终相对于汽车本身固定

网格参数

![[Pasted image 20240710224658.png]]

Convex:如果启用此属性,该 Mesh Collider 将与其他 Mesh Collider 发生碰撞。Convex Mesh Collider 最多 255 个三角形。

Cooking Options:启用或禁用影响物理引擎对网格处理方式的网格烹制选项。

  • None:禁用下方列出的所有 Cooking Options。
  • Everything:启用下方列出的所有 Cooking Options。
  • Cook for Faster Simulation:
    使物理引擎烹制网格以加快模拟速度。启用此设置后,这会运行一些额外步骤,以保证生成的网格对于运行时性能是最佳的。这会影响物理查询和接触生成的性能。禁用此设置后,物理引擎会使用更快的烹制速度,并尽可能快速生成结果。因此,烹制的 Mesh Collider 可能不是最佳的。
  • Enable Mesh Cleaning:
    使物理引擎清理网格。启用此设置后,烹制过程会尝试消除网格的退化三角形以及其他几何瑕疵。此过程生成的网格更适合于在碰撞检测中使用,往往可生成更准确的击中点。
  • Weld Colocated Vertices:
    使物理引擎在网格中删除相等的顶点。启用此设置后,物理引擎将合并具有相同位置的顶点。这对于运行时发生的碰撞反馈十分重要。

Mesh:引用需要用于碰撞的网格。

网格烹制
网格烹制将常规网格更改为可以在物理引擎中使用的网格。烹制会构建用于物理查询的空间搜索结构(如 Physics.Raycast)以及用于接触生成的支持结构。Unity 在碰撞检测中使用网格之前烹制所有这些网格。这可在导入时 (Import Settings > Model > Generate Colliders) 或运行时进行。

地形参数

![[Pasted image 20240710224640.png]]

Terrain Data:地形数据

Enable Tree Colliders:选中此属性时,将启用树碰撞体

1.3 碰撞检测函数

OnCollisionEnter(Collision collision)
OnCollisionStay(Collision collision)
OnCollisionExitCollision collision)

Collision参数

![[Pasted image 20240710230104.png]]

二、物理材质

决定交互方式 碰撞效果:是否有弹跳损失等
创建:Project右击->Create->Physic Material。注意2D和3D的区别

物理材质参数

在这里插入图片描述

Dynamic Friction:
已在移动时使用的摩擦力。通常为 0 到 1 之间的值。值为零就像冰一样,值为 1 将使对象迅速静止(除非用很大的力或重力推动对象)

Static Friction:
当对象静止在表面上时使用的摩擦力。通常为 0 到 1 之间的值。值为零就像冰一样,值为 1 将导致很难让对象移动。

Bounciness:
表面的弹性如何?值为 0 将不会反弹。值为 1 将在反弹时不产生任何能量损失,预计会有一些近似值,但可能只会给模拟增加少量能量。

Friction Combine:两个碰撞对象的摩擦力的组合方式。

  • Average:对两个摩擦值求平均值。
  • Minimum:使用两个值中的最小值。
  • Maximum:使用两个值中的最大值。
  • Multiply:两个摩擦值相乘。

Bounce Combine:
两个碰撞对象的弹性的组合方式。其模式与 Friction Combine 模式相同

三、触发检测

不产生物理效果的碰撞。2个碰撞器,1个刚体。
is trigger = true;

3.1 触发检测函数

OnTriggerEnter(Collider collider)
OnTriggerStay(Collider collider)
OnTriggerExit(Collider collider)

关键参数:Collider

在这里插入图片描述

<think>首先,用户的问题是:“我想了解或解决Unity中的碰撞问题请问Unity碰撞检测问题及解决方案”。这基于之前的引用内容,我需要根据系统指令来回答。系统指令:1.所有行内数学表达式使用$...$格式。2.独立公式使用$$...$$格式并单独成段。3.LaTeX语法正确。4.使用中文回答。5.生成相关问题。6.回答中引用的段落末尾自然地添加引用标识。用户的问题是关于Unity碰撞检测的问题及解决方案,所以我需要整合引用内容。引用内容:-[^1]:刚体配置不一致导致碰撞检测失效。-[^2]:Unity碰撞检测原理基于碰撞器和刚体。-[^3]:详细介绍了碰撞检测和触发检测的函数,以及关键条件。-[^4]:解决碰撞无法检测的问题,强调组件齐全和代码正确。-[^5]:使用八叉树优化碰撞检测。我的回答需要结构清晰,逐步解决问题。结构可以是:1.介绍Unity碰撞检测的基本原理。2.常见问题及其原因。3.解决方案。4.优化方法(如八叉树)。最后,生成相关问题。确保回答真实可靠,基于引用。使用中文回答。生成相关问题:在回答末尾添加相关问题,如示例中的“§§相关问题§§”。现在,规划回答结构:-**引言**:简述Unity碰撞检测的重要性。-**基本原理**:解释碰撞检测的核心组件(刚体和碰撞器),引用[^2]。-**常见问题**:-刚体缺失或不一致,引用[^1]。-其他问题如图层设置、代码错误,引用[^3]和[^4]。-**解决方案**:-确保刚体和碰撞器配置正确。-使用正确的碰撞检测函数(如OnCollisionEnter)。-检查图层矩阵等。-**优化方法**:引入八叉树或其他技术,引用[^5]。-**总结**。-**相关问题**。在引用末尾添加引用标识,例如:[^1]。数学表达式:用户问题中没有明显的数学内容,但如果涉及物理公式,可能需要。例如,碰撞检测可能涉及物理公式,但引用中没有提到具体公式,所以可能不需要数学表达式。但指令说所有行内数学表达式使用$...$,所以如果有,就使用。但在这个上下文中,可能没有,所以跳过。现在,撰写回答。</think>### Unity碰撞检测问题及解决方案 Unity中的碰撞检测是游戏开发的核心机制之一,它依赖于物理引擎来实现物体间的交互。然而,在开发过程中,开发者常遇到碰撞无法检测或触发失败等问题。这些问题通常源于配置错误、组件缺失或性能瓶颈。下面我将基于Unity的物理引擎原理,逐步分析常见问题并提供可靠解决方案。内容参考了Unity官方文档和最佳实践[^2][^3]。 #### 一、Unity碰撞检测的基本原理 Unity碰撞检测基于两个核心组件:**碰撞器(Collider)** 和**刚体(Rigidbody)**。碰撞器定义了物体的形状(如Box Collider、Sphere Collider),而刚体负责物理模拟(如重力、速度)。当两个物体发生交互时: - 如果两个物体都有**碰撞器但无刚体**,引擎可能忽略碰撞。 - 碰撞检测模式分为**物理碰撞(Collision)** 和**触发检测(Trigger)**: - **物理碰撞**:用于真实物理反应(如弹跳),需要调用事件函数如`OnCollisionEnter`。 - **触发检测**:用于区域检测(如进入陷阱),调用函数如`OnTriggerEnter`。 Unity物理引擎通过连续计算物体位置变化来实现检测,其效率依赖于正确配置[^2][^3]。 #### 二、常见问题及原因分析 以下是Unity碰撞检测中频发的问题,根源多与组件配置或代码实现相关: 1. **碰撞完全无法检测**:最常见原因是**刚体配置不一致**。例如,两个碰撞体均设置为Trigger但无刚体组件,引擎会忽略交互。引用[^1]指出:“若两个碰撞体均为Trigger且无刚体,引擎将忽略其交互。” 2. **碰撞事件未被触发**:可能由于: - **脚本错误**:事件函数(如`OnCollisionEnter`)未正确定义或绑定。 - **图层矩阵冲突**:Unity的图层(Layer)设置未允许碰撞(如未勾选“Layer Collision Matrix”)。 - **物理状态不同步**:一个物体是Kinematic刚体(仅脚本控制),另一个是动态刚体,导致检测失败[^3][^4]。 3. **性能低下导致检测遗漏**:在大规模场景中,物体过多时物理引擎不堪重负,导致碰撞事件延迟或丢失。引用[^5]提到:“物体分布极不均匀时,八叉树效率会下降。” 4. **其他问题**:包括碰撞点计算不准(如使用`Collision.contacts`错误)或触发器区域未正确设置。 #### 三、解决方案与步骤 针对上述问题,以下解决方案已验证有效,适用于Unity 2021+版本。逐步操作确保可靠性: 1. **确保组件配置正确**: - **添加刚体**:每个参与碰撞的物体必须附加Rigidbody组件。非物理物体可设置为Kinematic。 - **检查碰撞器类型**:确认Collider未勾选“Is Trigger”(除非需要触发检测)。引用[^1]强调:“通过显式配置刚体、同步物理状态、检查图层矩阵,可彻底解决此类问题。” - **验证图层设置**:在Unity编辑器中选择“Edit > Project Settings > Physics”,检查Layer Collision Matrix确保相关图层允许碰撞。 2. **修复脚本与事件函数**: - **正确实现事件函数**:在脚本中定义碰撞事件函数(如`OnCollisionEnter`),并确保脚本附加到物体上。示例代码: ```csharp // 物理碰撞检测示例 void OnCollisionEnter(Collision collision) { Debug.Log($"与 {collision.gameObject.name} 碰撞,接触点: {collision.contacts[0].point}"); } // 触发检测示例 void OnTriggerEnter(Collider other) { Debug.Log($"进入 {other.gameObject.name} 的触发区域"); } ``` 引用[^3]提醒:“代码中需正确处理`Collision`或`Collider`对象,避免空引用。” - **调试工具**:使用`Debug.Log`输出日志,确认事件是否触发。如引用[^4]所述:“两个物体的组件都是齐全的,代码也没有问题,但需检查日志输出。” 3. **优化性能以提升检测精度**: - **使用空间分区技术**:对于大型场景,引入**八叉树(Octree)** 优化。八叉树将场景划分为小区域,只检测邻近物体,大幅提升效率。引用[^5]建议:“八叉树只做‘粗筛选’,即快速找出可能碰撞的物体对,再交给Unity物理系统精确处理。” - 实现步骤: 1. 在Unity中集成八叉树管理器(如自定义脚本或Asset Store插件)。 2. 设置参数:`maxObjectsPerNode`(每个节点最大物体数,推荐10-20)和`maxDepth`(树最大深度,推荐5-8)。 3. 结合物理引擎:八叉树筛选后调用`Physics.CheckCollision`。 - **减少GC压力**:复用对象列表,避免频繁内存分配。 4. **通用排查清单**: - 重启Unity编辑器,有时缓存问题导致检测失效。 - 检查物体缩放比例(Scale),过大或过小可能影响碰撞计算。 - 确保物体在场景中激活(Active),且Rigidbody未冻结(Freeze Position/Rotation)。 #### 四、总结 Unity碰撞检测问题多由刚体缺失、脚本错误或性能不足引起。通过正确配置组件(确保每个碰撞体有刚体)、实现事件函数和采用优化技术(如八叉树),可高效解决[^1][^5]。实践中,结合Unity的物理调试视图(Physics Debugger)可加速问题定位。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值