Unity 2D碰撞检测的简单使用

2022年3月4日 10763点热度 14人点赞 0条评论

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想要参与到碰撞检测中,需要两个条件:

  1. 必须拥有一个collider组件(必须)
  2. 拥有一个rigibody组件,这个是可选的。如果两个Game Object 想要触发碰撞,那么必须要其中一个拥有rigibody组件。

Rigidbody 2D

这个组件可以为GameObject 添加物理效果,可以设置重力、摩擦力、弹力等属性,并且可以在与其他对象碰撞的时候会显示出物理效果。

image-20220427194833858

BodyType

有三种类型可以选择:

  1. Dynamic 类型会响应所有物理效果,在碰撞到物体会发生位移,旋转。
  2. Kinematic 不会响应物理效果,不受力的影响,但是可以通过Rigidbody2d.movePosstion来移动它。
  3. Static 表示一个不会动的物体,质量无限大,且不会收到力的作用,也不能通过RIgidbody2d的函数来进行移动或者旋转。

注意:Dynamic 可以和所有类型的Rigidbody产生碰撞,其他类型只能和dynamic类型产生碰撞

以下是其他可以调整的属性:

属性: 功能:
Body Type 设置 2D 刚体的组件设置,从而可操纵移动(位置和旋转)行为和 2D 碰撞体交互。 选项为:DynamicKinematicStatic
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

碰撞检测的体现,有两种:

  1. 直接在游戏画面上体现如玩家控制的角色前面出现了一堵墙,正常情况下是不允许角色穿过墙体的,那么这个时候可以使用碰撞检测实现这样的功能。
  2. 在代码里被获取碰撞事件,然后在碰撞的时候做一些事情。

img

这是在inspector window中看到的 Box Collider 2D的属性面板。

这里有两个比较重要的属性:

  1. 包围盒,为Game Object 添加 collider 组件的时候unity会默认将包围盒的大小设置为和Game Object一样,如果需要修改可以点击Edit Collider 右边的按钮,就可以在scene windows拖拽修改包围盒的大小。
  2. Is Trigger ,这个属性是默认不勾选的,这个时候Game Object会正常响应碰撞检测,也会仿真rigibody上的物理效果。如果勾选了这个属性,那么Game Object不会仿真物理属性,但是在被碰撞的时候会调用脚本中的 void onTriggerEnter2D(Collision2D collision)函数

这里还需要了解两个函数:

  1. void OnCollisionEnter2D(Collision2D collision);
  2. 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 触发

运行结果:

img

img

最后的结果也基本在预料之中

结论
  1. 两个对象都不勾选Is Trigger 碰撞时会有物理效果,且会在脚本里调用collision函数。
  2. 两个对象中只要有一个勾选Is Trigger,碰撞时会触发Trigger 函数,并且不会有物理效果。

关于碰撞检测的基本使用就是以上,碰撞检测的项目放到了这里:https://gitee.com/dalianmiaomiao/learn-unity2-d/tree/master/collid

大脸猫

这个人虽然很勤快,但什么也没有留下!

文章评论