Unity的碰撞检测(一)

(一)测试前准备工作

        1.创建两个游戏对象,分别取名为”Player”和”Enemy”,并且为名为”Player”的游戏对象设置Tag也为”Player”,二者在场景中如图1所示:

图 1 绿为Enemy,红为Player

        2.编写脚本组件”TriggerTest”,并挂载到Enemy上,代码如下所示:

using UnityEngine;

public class TriggerTest : MonoBehaviour
{
    /*碰撞器为触发器的碰撞检测方法如下三个*/
    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Player")) Debug.Log("Trigger Enter");
    }

    private void OnTriggerStay2D(Collider2D other)
    {
        if (other.CompareTag("Player")) Debug.Log("Trigger");
    }

    private void OnTriggerExit2D(Collider2D other)
    {
        if (other.CompareTag("Player")) Debug.Log("Trigger Exit");
    }

    /*碰撞器不为触发器的碰撞检测方法如下三个*/
    private void OnCollisionEnter2D(Collision2D other)
    {
        if (other.transform.CompareTag("Player")) Debug.Log("Collider Enter");
    }

    private void OnCollisionStay2D(Collision2D other)
    {
        if (other.transform.CompareTag("Player")) Debug.Log("Collider");
    }

    private void OnCollisionExit2D(Collision2D other)
    {
        if (other.transform.CompareTag("Player")) Debug.Log("Collider Exit");
    }
}

        3.Trigger输出:输出”Trigger Enter”或”Trigger”或”Trigger Exit”;

       4.Collider输出:输出”Collider Enter”或” Collider”或” Collider Exit”。

(二)测试用例

        (1)测试约定:

       碰撞器统一使用BoxCollider2D组件,刚体统一使用Rigidbody2D组件,测试涉及更改的属性有且仅有碰撞器的激活或禁用和IsTrigger两个属性,刚体的挂载或卸载,且二者默认属性分别如图2和图3所示:

图 2 BoxCollider2D默认属性
图 3 Rigidbody2D默认属性

        (2)非法测试用例:

       A2、A3、A6、A7、A11、A12、A14、A15与(一)中预设冲突,故舍弃。

       B1、B4、B5、B8、B9、B10、B13、B16与(一)中预设冲突,故舍弃。

       A9、A10、A13、A16未挂载碰撞器是一定不可能发生碰撞的测试用例,故舍弃。

       B11、B12、B14、B15未挂载碰撞器是一定不可能发生碰撞的测试用例,故舍弃。

表 1 测试用例

游戏对象

用例序号

是否激活碰撞器

是否挂载刚体

是否挂载TriggerTest

碰撞器是否为触发器

Player

A1

√

×

×

×

A2

√

x

√

×

A3

√

x

√

√

A4

√

×

×

√

A5

√

√

×

×

A6

√

√

√

×

A7

√

√

√

√

A8

√

√

×

√

A9

×

×

×

×

A10

×

√

×

×

A11

×

√

√

×

A12

×

√

√

√

A13

×

√

×

√

A14

×

×

√

×

A15

×

×

√

√

A16

×

×

×

√

Enemy

B1

√

×

×

×

B2

√

x

√

×

B3

√

x

√

√

B4

√

×

×

√

B5

√

√

×

×

B6

√

√

√

×

B7

√

√

√

√

B8

√

√

×

√

B9

×

×

×

×

B10

×

√

×

×

B11

×

√

√

×

B12

×

√

√

√

B13

×

√

×

√

B14

×

×

√

×

B15

×

×

√

√

B16

×

×

×

√

表 2 测试用例组合

组合序号

测试用例组合

控制台输出

G1

A1、B2

无

G2

A1、B3

无

G3

A1、B6

无

G4

A1、B7

Trigger输出

G5

A4、B2

无

G6

A4、B3

无

G7

A4、B6

Trigger输出

G8

A4、B7

Trigger输出

G9

A5、B2

无

G10

A5、B3

Trigger输出

G11

A5、B6

无

G12

A5、B7

Trigger输出

G13

A8、B2

Trigger输出

G14

A8、B3

Trigger输出

G15

A8、B6

Trigger输出

G16

A8、B7

Trigger输出

(三)测试总结   

        分析1:对比G4、G8、G12、G16可知,当Enemy具备触发器+刚体时,无论Player的碰撞器是否为触发器或者是否具备刚体,都执行触发器的检测。

       分析2:对比G7和G8可知,当Player仅具备触发器且Enemy具备刚体时,无论Enemy的碰撞器是否为触发器均执行触发器的检测。

       分析3:对比G10和G12可知,当Player具备碰撞器+刚体且Enemy具备触发器时,无论Enemy是否具备刚体均执行触发器的检测。

       分析4:对比G13-G16可知,当Player具备触发器+刚体时,无论Enemy的碰撞器是否为触发器或者是否具备刚体,都执行触发器的检测。

       由分析1-4可知,有效触发的必要条件如下:

       结论1:两个游戏对象必须有至少一个触发器。

       结论2:两个游戏对象至少有一个具备刚体。

(四)碰撞检测相关的API

       (1)OnCollisionEnter()和OnCollisionEnter2D();

       (2)OnCollisionStay()和OnCollisionStay2D();

       (3)OnCollisionExit()和OnCollisionExit2D();

       (4)OnTriggerEnter()和OnTriggerEnter2D();

       (5)OnTriggerStay()和OnTriggerStay2D();

       (6)OnTriggerExit()和OnTriggerExit2D();

        具体看官方关于Monobehaviour类的说明。

(五)问题

       在上面的测试中我们并没有得到Collider输出,所有的输出都是Trigger输出,这个问题的原因是啥?我们在下一篇“Unity的碰撞检测(二)”继续探讨吧。

如果这篇文章对你有帮助,请给作者点个赞吧!