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的碰撞检测(二)”继续探讨吧。

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