Unity实用功能之触发检测和碰撞检测

4,752 阅读5分钟

这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战

概述

上篇文章写道Untiy的射线检测,本篇文章主要介绍下Untiy中的触发器和碰撞器。在日常项目开发中,经常会用到碰撞检测,而在Unity中,对于游戏对象的碰撞检测有多种方法,今后在开发的过程中,可视情况而定,选用哪一种检测方法。两种方法分别为碰撞检测和触发检测。下面就让我们一起来了解一下。

碰撞

想要物体产生碰撞,那么物体必须添加刚体(Rigidbody)和碰撞器,刚体可以让物体在物理影响下运动。碰撞体是物理组件的一类,它要与刚体一起添加到游戏对象上才能触发碰撞。如果两个刚体相互撞在一起,除非两个对象有碰撞体时物理引擎才会计算碰撞,在物理模拟中,没有碰撞体的刚体会彼此相互穿过。

碰撞的必要条件

在Unity中发生碰撞的必要条件为,两个物体都必须带有碰撞器(Collider),其中一个物体还必须带有Rigidbody刚体。

碰撞检测

碰撞检测,当两个物体发生碰撞时的检测,这两个物体一般不会发生穿透的情况。其检测状态一共有三个。
碰撞检测涉及三个函数:

  1. 当与物体碰撞的一瞬间:OnCollisionEnter(Collision collision)collisionInfo是撞到的物体的碰撞信息;
  2. 当在与物体持续碰撞接触期间:OnCollisionStay(Collision collision);
  3. 当与物体不再接触:OnCollisionExit(Collision collision)。

触发检测

触发检测,就是放两个物体发生碰撞时,不会发生弹开等物体效果,想要实现触发检测,需要将物体身上的collider上的属性Is Tigger勾选上,此时就不会发生碰撞,该物体就变成了一个触发器可以被物体穿过。
触发器的三个函数:

  1. 当物体碰到触发器的时候:OnTriggerEnter(Collider collider)
  2. 当物体一直在和触发器接触时:OntriggerStay(Conllider collider)
  3. 当物体不再和触发器接触时:OnTriggerExit(Collider colliser)

碰撞器和触发器的区别

碰撞器是触发器的载体,而触发器只是碰撞器身上的一个属性。

  • Is Trigger=false时,碰撞器根据物理引擎引发碰撞,产生碰撞的效果,可以调用OnCollisionEnter/Stay/Exit函数;
  • Is Trigger=true时,碰撞器被物理引擎所忽略,没有碰撞效果,可以调用OnTriggerEnter/Stay/Exit函数。 如果既要检测到物体的接触又不想让碰撞检测影响物体移动或要检测一个物件是否经过空间中的某个区域这时就可以用到触发器
    碰撞器一般可以用在汽车的碰撞等 触发器一般可以用在检测某一物体是否经过某一个位置等。

UI碰撞

ui的碰撞原理和上面是一样的,只不过UI用到的Collider都是UI专用的,所以函数也相应的有所变化,要使用如下函数
碰撞

  • OnCollisionEnter2D(Collision2D collision)
  • OnCollisionStay2D(Collision2D collision)
  • OnCollisionExit2D(Collision2D collision) 触发
  • OnTriggerEnter2D(Collider2D collision)
  • OnTriggerStay2D(Collider2D collision)
  • OnTriggerExit2D(Collider2D collision)

注意

  • OnCollisionEnter方法必须是在两个碰撞物体都不勾选isTrigger的前提下才能进入,反之只要勾选一个isTrigger那么就能进入OnTriggerEnter方法。
  • OnCollisionEnterOnTriggerEnter是冲突的不能同时存在的。
  • 若物体A添加了刚体,物体B没有添加刚体,A去碰撞B,则A会被弹开,B不会运动,此时A、B都会触发OnCollisionEnter方法。
  • 若物体A添加了刚体,物体B没有添加刚体,B去碰撞A,不会发生碰撞效果,此时A和B都不会触发OnCollisionEnter方法。 所以,一定要确认好刚体添加在哪个物体身上,如果两个物体都有,则不会出现上述问题

两种方法的代码

碰撞

三维场景的碰撞

  private void OnCollisionEnter(Collision collision)
    {
        Debug.Log("开始碰撞" + collision.collider.gameObject.name);
    }
    private void OnCollisionStay(Collision collision)
    {
        Debug.Log("持续碰撞中" + collision.collider.gameObject.name);
    }
    private void OnCollisionExit(Collision collision)
    {
        Debug.Log("碰撞结束" + collision.collider.gameObject.name);
    }

UI的碰撞

 private void OnCollisionEnter2D(Collision2D collision)
    {
        
    }
    private void OnCollisionStay2D(Collision2D collision)
    {
        
    }
    private void OnCollisionExit2D(Collision2D collision)
    {
        
    }

触发

三维场景的触发

private void OnTriggerEnter(Collider other)
    {
        Debug.Log("触发器开始出发:" + other.gameObject.name);
    }

    private void OnTriggerStay(Collider other)
    {
        Debug.Log("触发器检测中:" + other.gameObject.name);
    }

    private void OnTriggerExit(Collider other)
    {
        Debug.Log("触发器结束:" + other.gameObject.name);
    }

UI的触发

 private void OnTriggerEnter2D(Collider2D collision)
    {
        
    }
    private void OnTriggerStay2D(Collider2D collision)
    {
        
    }
    private void OnTriggerExit2D(Collider2D collision)
    {
        
    }

总结

  • OnCollisionEnter方法要求碰撞的发起方必须拥有刚体,而被碰撞方有没有刚体并不重要。OnTriggerEnter方法则对此没有要求,只需要碰撞双方有一个具有刚体即可触发。即刚体是一个判断是否实现碰撞的是与否的标志。
  • 刚体对于系统的开销是很大的,所以在使用刚体时,根据可能发生的碰撞触发事件,适当的减少刚体,是一个减少资源消耗的好办法。 比如地面就可以不设置刚体,因为地面是永远不动的,把人物设置刚体就可以实现真实的物理碰撞效果了。

写在最后

所有分享的内容均为作者在日常开发过程中使用过的各种小功能点,分享出来也变相的回顾一下,如有写的不好的地方还请多多指教。欢迎大家相互学习进步。