Unity的碰撞检测(一)
(一)测试前准备工作
1.创建两个游戏对象,分别取名为”Player”和”Enemy”,并且为名为”Player”的游戏对象设置Tag也为”Player”,二者在场景中如图1所示:
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)非法测试用例:
A2、A3、A6、A7、A11、A12、A14、A15与(一)中预设冲突,故舍弃。
B1、B4、B5、B8、B9、B10、B13、B16与(一)中预设冲突,故舍弃。
A9、A10、A13、A16未挂载碰撞器是一定不可能发生碰撞的测试用例,故舍弃。
B11、B12、B14、B15未挂载碰撞器是一定不可能发生碰撞的测试用例,故舍弃。
游戏对象 |
用例序号 |
是否激活碰撞器 |
是否挂载刚体 |
是否挂载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 |
× |
× |
× |
√ |
组合序号 |
测试用例组合 |
控制台输出 |
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的碰撞检测(二)”继续探讨吧。
如果这篇文章对你有帮助,请给作者点个赞吧!