[Unity]碰撞器的接触捕获层详解

前言

本文详细介绍了Unity引擎Collider2D组件的Layer Overrides属性栏的属性Contact Capture Layers,即接触捕获层
如果你在项目中遇到了问题,但不确定是否是接触捕获层的设置错误导致的,请跳转至相关问题汇总查询。

本文的所有解释基于Unity 2023.2官方文档,具有时效性,若Unity版本更迭导致解释失效,欢迎留言指正!

※关闭效果器(Effector)的遮罩

如果你希望在Unity工程中对本文内容进行验证,并且实验对象的碰撞器(Collider)勾选了由效果器使用,请取消勾选效果器的使用碰撞器遮罩选项,否则效果器的遮罩会覆盖碰撞器的Layer Overriders属性,导致实验结果与预期不符。

接触捕获层的官方描述

Unity Decumentation - Collider2D.contactCaptureLayers
请添加图片描述

官方描述的翻译和注解

接触捕获层作用简介

接触捕获层:与当前Collider2D接触的层,如果在Contact Capture Layers中被勾选,那么接触将被捕获

接触(Contact)和捕获(Capture)

接触由物理系统产生,用于计算碰撞响应等行为。
接触是自动生成的,只需要捕获接触就可以对其执行物理查询或生成物理回调

物理查询】IsTouching、IsTouchingLayers/GetContacts等用于检测和查询物理接触情况的方法。
注意,BoxCast、RayCast等方法和此处的物理查询不同,这些方法通过数学计算来预测和检测物体是否会与其他物体相交,因此不需要接触捕获
物理回调】OnCollisionEnter、OnCollisionExit、OnTriggerEnter、OnTriggerExit等特定的物理事件发生时被自动调用的方法。

通常,所有接触层都会被捕获和存储,但这会导致处理时间和内存消耗增加。
因此,只选择需要的层进行捕获,可以提高性能并降低整体内存消耗;
但是未捕获的层的接触,在物理查询中不可用,也不会产生物理回调。

接触层
由层级碰撞矩阵、Layer Overrides的包含层和排除层决定。
值得注意,不是所有接触层都会被捕获,只有被捕获的接触层才能进行物理查询、产生物理回调。

配置接触捕获层的作用

通过配置接触捕获层,可以确保只接收来自选定层的响应。

这意味着在C#脚本中,可以只关心特定层的物理事件。

※接触捕获层对碰撞响应的影响

接触的捕获不会影响碰撞响应,因为接触在捕获之前总是由物理系统处理的。

【注】如果你希望禁用两个物体的碰撞响应,或者你不希望A物体和B物体之间产生任何物理互动,在接触捕获层中取消勾选是无法实现的。因为接触捕获层只负责启用/禁用物理查询和物理回调。
正确的做法:
1.如果你希望完全无视A和B的接触:在全局碰撞矩阵中取消勾选A和B所在的Layer,或者在A或B的排除层(Exclude Layers)中取消勾选B所在的图层。
e.g.人物和人物发射的子弹
2.如果你希望A不对B产生力的效果,但是需要获取A和B的碰撞信息:允许A和B的接触(在全局碰撞矩阵中勾选A和B所在的Layer,或者在A或B的包含层(Include Layers)中勾选B所在的图层),但是在A的力发送层(Force Send Layers)取消勾选B所在的图层。同理,或者在B的力接收层(Force Receive Layers)取消勾选A所在的图层。
e.g.人物和怪物发射的子弹(无击退)

需要接触捕获的物理查询

Physics2D.IsTouching
Rigidbody2D.IsTouching
Collider2D.IsTouching
Physics2D.IsTouchingLayers
Rigidbody2D.IsTouchingLayers
Collider2D.IsTouchingLayers
Physics2D.GetContacts
Rigidbody2D.GetContacts
Collider2D.GetContacts

需要接触捕获的物理回调

OnCollisionEnter2D
OnCollisionStay2D
OnCollisionExit2D
OnTriggerEnter2D
OnTriggerStay2D
OnTriggerExit2D

【注】即常用的6个碰撞回调/触发回调

注意

此属性不控制碰撞体是否会接触,而只是控制是否捕获接触以进行查询和回调。
即使在Callback Layers中选择了所有层,也只会报告那些被捕获的层。

【注】这一点在上文(接触捕获层对碰撞响应的影响)已经详细解释

运行时(Runtime)修改

修改接触捕获层将导致所有接触信息被销毁。
仍然有效的接触将通过物理回调报告为新的接触信息。
由于此属性(接触捕获层)会破坏现有接触信息,如果需要通过物理回调跟踪接触状态,不建议在运行时更改此属性。

接触的相互性

接触是相互的,如果接触中的任何一个碰撞体禁用了对接触的捕获,那么双方都不会看到接触。

总结

当某个层的接触捕获功能关闭时,该层的接触查询将不会返回结果,也不会产生任何回调。

总的来说,接触捕获层,名副其实,只负责启用/禁用对接触的捕获,没有被捕获的接触,物理查询没有结果,也不会产生回调。接触捕获层,不负责启用/禁用接触,所以即使禁用了接触捕获,A物体仍然会被B物体所阻挡!

相关问题汇总

出现以下问题时,也许不是接触捕获层设置错误导致的,请检查其他设置。

1.怎样完全无视A和B的任何接触和碰撞?

在全局碰撞矩阵中取消勾选A和B的Layer
确保A和B的Collider都没有在包含层中取消勾选对方的Layer
如果A和B的Collider使用了Effector,取消勾选Effector的遮罩

2.怎样允许A和B的接触,但禁用A和B之间的物理碰撞?

方案一:把一方设置为Trigger
方案二:取消勾选力发送/接收层
允许接触:
在全局碰撞矩阵中勾选A和B的Layer
或者在A或B的Collider的包含层中勾选对方的Layer
禁用物理碰撞:
取消勾选一方的力发送/接收层

3.为什么全局碰撞矩阵/包含层/排除层失效了?

关闭效果器(Effector)的遮罩!!!
关闭效果器(Effector)的遮罩!!!
关闭效果器(Effector)的遮罩!!!
检查层覆盖优先级(Layer Override Priority)!!!
检查层覆盖优先级(Layer Override Priority)!!!
检查层覆盖优先级(Layer Override Priority)!!!
碰撞器中使用了由复合使用由效果器使用的尤其注意。

相关推荐

  1. unity车辆碰撞检测

    2024-07-15 19:26:04       87 阅读
  2. Unity游戏引擎2D碰撞检测

    2024-07-15 19:26:04       66 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-15 19:26:04       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-15 19:26:04       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-15 19:26:04       58 阅读
  4. Python语言-面向对象

    2024-07-15 19:26:04       69 阅读

热门阅读

  1. Redis Cluster 工具

    2024-07-15 19:26:04       15 阅读
  2. leensa注册码

    2024-07-15 19:26:04       26 阅读
  3. vue 导出excel乱码问题

    2024-07-15 19:26:04       15 阅读
  4. tomcat

    tomcat

    2024-07-15 19:26:04      19 阅读
  5. C++ STL中的std::remove_if 的用法详解

    2024-07-15 19:26:04       21 阅读