Unity 2D碰撞检测
前言
游戏的制作过程中常常需要检测两个物体是否接触,unity为了方便开发者实现这样的功能提供了collider 和 rigbody 这两个组件。
collider它会为Game Obejct提供一个碰撞包围盒,然后每间隔0.02秒会计算一次包围盒是否和其他的包围盒重合,由此来检测物体的碰撞。
rigibody也称之为刚体,它会为Game Object 提供一系列的物理效果,如重力、摩擦力、弹力、受力反馈等,这里不多叙述unity物理引擎的使用,只记录rigibody在碰撞检测中发挥的作用。
注: unity提供了许多种类的collider 和rigibody组件,这里只记录 box collider 2D 与rigibody 2D的使用方法。
哪些Game Object会参与碰撞检测?
Game Object想要参与到碰撞检测中,需要两个条件:
- 必须拥有一个collider组件(必须)
- 拥有一个rigibody组件,这个是可选的。如果两个Game Object 想要触发碰撞,那么必须要其中一个拥有rigibody组件。
Rigidbody 2D
这个组件可以为GameObject 添加物理效果,可以设置重力、摩擦力、弹力等属性,并且可以在与其他对象碰撞的时候会显示出物理效果。
BodyType
有三种类型可以选择:
- Dynamic 类型会响应所有物理效果,在碰撞到物体会发生位移,旋转。
- Kinematic 不会响应物理效果,不受力的影响,但是可以通过Rigidbody2d.movePosstion来移动它。
- Static 表示一个不会动的物体,质量无限大,且不会收到力的作用,也不能通过RIgidbody2d的函数来进行移动或者旋转。
注意:Dynamic 可以和所有类型的Rigidbody产生碰撞,其他类型只能和dynamic类型产生碰撞
以下是其他可以调整的属性:
属性: | 功能: |
---|---|
Body Type | 设置 2D 刚体的组件设置,从而可操纵移动(位置和旋转)行为和 2D 碰撞体交互。 选项为:Dynamic、Kinematic、Static |
Material | 使用此属性可为连接到特定父 2D 刚体的所有 2D 碰撞体指定公共材质。 注意:2D 碰撞体使用自己的 Material 属性(如果已设置)。如果此处或在 2D 碰撞体中未指定材质,则默认选项为 None (Physics Material 2D)。这种情况下使用可在 Physics 2D 窗口中设置的默认材质。 2D 碰撞体使用以下优先级顺序来确定要使用的 Material 设置: 1. 在 2D 碰撞体上指定的 2D 物理材质。 2.在附加的 2D 刚体上指定的 2D 物理材质。 在 Physics 2D 窗口中指定的 2D 物理材质默认材质。 提示:使用此设置确保附加到同一 Static Body Type 2D 刚体的所有 2D 碰撞体都可使用同一材质。 |
Simulated | 如果希望 2D 刚体以及所有附加的 2D 碰撞体和 2D 关节在运行时与物理模拟系统交互,请启用 Simulated__(选中复选框)。如果禁用此功能(取消选中复选框),这些组件不会与模拟系统进行交互。请参阅下面的 2D 刚体属性:Simulated 以了解更多详细信息。默认情况下会选中此框。 | | Use Auto Mass__ |
Mass | 定义 2D 刚体的质量。如果已选中 Use Auto Mass,此属性将显示灰色。 |
Linear Drag | 一种会影响位置移动的阻力系数。 |
Angular Drag | 一种会影响旋转移动的阻力系数。 |
Gravity Scale | 定义游戏对象受重力影响的程度。 |
Collision Detection | 定义如何检测 2D 碰撞体之间的碰撞。 |
Discrete | 将 Collision Detection 设置为 Discrete 时,具有 2D 刚体和 2D 碰撞体的游戏对象在物理更新期间可以重叠或穿过彼此(如果移动得足够快)。仅会在新位置生成碰撞触点。 |
Continuous | Collision Detection 设置为 Continuous 时,具有 2D 刚体和 2D 碰撞体的游戏对象在更新期间不会穿过彼此。相反,Unity 会计算 2D 碰撞体的第一个影响点,并将游戏对象移动到该点。请注意,此设置比 Discrete 耗费更多 CPU 时间。 |
Sleeping Mode | 定义游戏对象如何在处于静止状态时“睡眠”以节省处理器时间。 |
Never Sleep | 禁用睡眠(应尽可能避免此设置,否则会影响系统资源)。 |
Start Awake | 游戏对象最初处于唤醒状态。 |
Start Asleep | 游戏对象最初处于睡眠状态,但可以被碰撞唤醒。 |
Interpolate | 定义如何在物理更新间隔之间插入游戏对象的移动(运动趋于颠簸状态时很有用)。 |
None | 不应用移动平滑。 |
Interpolate | 根据游戏对象在先前帧中的位置来平滑移动。 |
Extrapolate | 根据游戏对象在下一帧中的估计位置来平滑移动。 |
Constraints | 定义对 2D 刚体运动的任何限制。 |
Freeze Position | 选择性停止 2D 刚体沿世界 X 和 Y 轴的移动。 |
Freeze Rotation | 选择性停止 2D 刚体围绕 Z 轴的旋转。 |
RIgidbody在碰撞时,使用的是collide对象的包围盒,所以在使用Rigidbody对象时一定要添加一个collide组件。
Box Collider 2D
碰撞检测的体现,有两种:
- 直接在游戏画面上体现如玩家控制的角色前面出现了一堵墙,正常情况下是不允许角色穿过墙体的,那么这个时候可以使用碰撞检测实现这样的功能。
- 在代码里被获取碰撞事件,然后在碰撞的时候做一些事情。
这是在inspector window中看到的 Box Collider 2D的属性面板。
这里有两个比较重要的属性:
- 包围盒,为Game Object 添加 collider 组件的时候unity会默认将包围盒的大小设置为和Game Object一样,如果需要修改可以点击Edit Collider 右边的按钮,就可以在scene windows拖拽修改包围盒的大小。
- Is Trigger ,这个属性是默认不勾选的,这个时候Game Object会正常响应碰撞检测,也会仿真rigibody上的物理效果。如果勾选了这个属性,那么Game Object不会仿真物理属性,但是在被碰撞的时候会调用脚本中的 void onTriggerEnter2D(Collision2D collision)函数
这里还需要了解两个函数:
- void OnCollisionEnter2D(Collision2D collision);
- void OnTriggerEnter2D(Collider2D collision);
这两个函数会在碰撞开始时被调用,他们的区别是collision会在Collider的Is Trigger属性没被勾选的时候被调用,Trigger则相反。
Box Collider 2D 使用测试
主要主要是想测试Is Trigger这个属性的影响,所以创建了两个精灵,car与person。然后两个一组复制了四组,四组分别为设置不同的is Trigger属性。
car的脚本:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class go : MonoBehaviour { public int speed = 4; public int group = 0; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { transform.position = Vector3.Lerp(transform.position, transform.position + Vector3.right * speed, Time.deltaTime); } private void OnCollisionEnter2D(Collision2D collision) { Debug.Log("Collison--组" + group + ":你TM撞我车是吧?"); } private void OnTriggerEnter2D(Collider2D collision) { Debug.Log("Tregger--组" + group + ":你TM撞我车是吧?"); } }
person的脚本:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class person : MonoBehaviour { public int group = 0; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } private void OnCollisionEnter2D(Collision2D collision) { Debug.Log("Collison--组" + group + ":撞了人你还想走?"); } private void OnTriggerEnter2D(Collider2D collision) { Debug.Log("Trigger--组" + group + ":撞了人你还想走?"); } }
注:两只精灵都有Box Collider 2D组件,只有car 拥有rigibody 2D组件。
Is Trigger 属性勾选情况:
第一组 | car | 不触发 | person | 不触发 |
---|---|---|---|---|
第二组 | car | 不触发 | person | 触发 |
第三组 | car | 触发 | person | 不触发 |
第四组 | car | 触发 | person | 触发 |
运行结果:
最后的结果也基本在预料之中
结论
- 两个对象都不勾选Is Trigger 碰撞时会有物理效果,且会在脚本里调用collision函数。
- 两个对象中只要有一个勾选Is Trigger,碰撞时会触发Trigger 函数,并且不会有物理效果。
关于碰撞检测的基本使用就是以上,碰撞检测的项目放到了这里:https://gitee.com/dalianmiaomiao/learn-unity2-d/tree/master/collid
文章评论