• Unity 碰撞检测中碰撞器与触发器的区别


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

    物体发生碰撞的必要条件
    两个物体都必须带有碰撞器(Collider),其中一个物体还必须带有Rigidbody刚体。
    在unity3d中,能检测碰撞发生的方式有两种,一种是利用碰撞器,另一种则是利用触发器。
     
    碰撞器:一群组件,它包含了很多种类,比如:Box Collider(盒碰撞体),Mesh Collider(网格碰撞体)等,这些碰撞器应用的场合不同,但都必须加到GameObjecet身上。
    触发器,只需要在检视面板中的碰撞器组件中勾选IsTrigger属性选择框。
     
    触发信息检测:
    1.MonoBehaviour.OnTriggerEnter(Collider collider)当进入触发器
    2.MonoBehaviour.OnTriggerExit(Collider collider)当退出触发器
    3.MonoBehaviour.OnTriggerStay(Collider collider)当逗留触发器
     
    碰撞信息检测:
    1.MonoBehaviour.OnCollisionEnter(Collision collision) 当进入碰撞器
    2.MonoBehaviour.OnCollisionExit(Collision collision) 当退出碰撞器
    3.MonoBehaviour.OnCollisionStay(Collision collision)  当逗留碰撞器
     
    两个物体相接触时到底执行OnTriggerEnter还是执行OnCollisionEnter方法,这两个又有什么区别呢?
    为了验证碰撞器与触发器的区别,现设计一个简单的游戏,让小汽车与小球发生碰撞。新建一个C#脚本文件,把它拖给小汽车对象,双击该脚本文件进入脚本编辑器,在该脚本中加入如下两个方法,并分别设置一个断点:
    void OnTriggerEnter(Collider collider)
    {
         //进入触发器执行的代码
    }
    void OnCollisionEnter(Collision collision) 
    {
         //进入碰撞器执行的代码
    }
    当未勾选碰撞器的Is Trigger选项时汽车与球体发生碰撞,进入方法OnCollisionEnter,碰撞之后汽车产生被球体撞飞的效果:
    如果将碰撞器的Is Trigger属性选中,再次启动游戏让球体与汽车产生接触,这时进入方法OnTriggerEnter。之后球体直接穿过汽车,但球体与汽车都没有产生碰撞效果:
    unity3d中的碰撞器和触发器的区别?
     
    碰撞器是触发器的载体,而触发器只是碰撞器身上的一个属性
    当Is Trigger=false时,碰撞器根据物理引擎引发碰撞,产生碰撞的效果,可以调用OnCollisionEnter/Stay/Exit函数;
    当Is Trigger=true时,碰撞器被物理引擎所忽略,没有碰撞效果,可以调用OnTriggerEnter/Stay/Exit函数。
     
    如果既要检测到物体的接触又不想让碰撞检测影响物体移动或要检测一个物件是否经过空间中的某个区域这时就可以用到触发器
     
    例子:
    碰撞器:汽车被撞飞、皮球掉在地上又弹起效果
    触发器:人站在靠近门的位置门自动打开效果
     
     
    另外一篇文章:
     

    unity3d 理解刚体(Rigidbody)和碰撞体(Collider)以及触发器(Is Trigger),边学边更新 

    刚体(Rigidbody)的官方(摘自Unity3d的官方指导书《Unity4.x从入门到精通》)解释如下:

    Rigidbody(刚体)组件可使游戏对象在物理系统的控制下来运动,刚体可接受外力与扭矩力用来保证游戏对象像在真实世界中那样进行运动。任何游戏对象只有添加了刚体组件才能受到重力的影响,通过脚本为游戏对象添加的作用力以及通过NVIDIA物理引擎与其他的游戏对象发生互动的运算都需要游戏对象添加了刚体组件。

    个人理解就是刚体是用来模拟物体受到一个力作用时候的表现,这个从刚体中的参数就可以看出:

    全是关于物体受到力之后,怎么运动的参数,比如Mass质量,Drag阻力。

    碰撞体的官方(摘自Unity3d的官方指导书《Unity4.x从入门到精通》)解释如下:

    碰撞体是物理组件的一类,它要与刚体一起添加到游戏对象上才能触发碰撞。如果两个刚体相互撞在一起,除非两个对象有碰撞体时物理引擎才会计算碰撞,在物理模拟中,没有碰撞体的刚体会彼此相互穿过。

    个人是这样理解的,为什么要判断碰撞,判断碰撞就是需要计算力,无论是阻力也好,动力也好,如果此时物体有刚体组件,那么物体就会在力的作用下运动。如果这个物体没有刚体,那么碰撞产生的力就没有任何意义了,那计算碰撞也就没有任何意义了。

    所以,我们可以推断出,如果两个碰撞体都没有刚体组件,那么这两个物体即使相互发生了碰撞,那么也不会有碰撞事件的。

    官网上的碰撞的图如下(注:据说是官网的图,我在网上很多地方看到了,但我目前为止还没找到在官网的哪个位置哈):

    从上面的图中我们看出来碰撞的双方中一定要有一个Rigidbody存在,并且碰撞双方必须都要有碰撞体组件。

    但做实验的时候发现了一个很诡异的事情,就是发生碰撞的主体一定是要带刚体的,即只有带刚体的碰撞体去撞其他碰撞体时,双方才会收到碰撞事件,以下是我做的实验:

    一、控制A(刚体加碰撞体)撞击 静止的B(只有碰撞体),双方能收到碰撞事件。

    二、控制B(只有碰撞体)撞击 静止的A(刚体加碰撞体),双方收不到碰撞事件。

    三、让A(刚体加碰撞体)自由下落,然后控制B(只有碰撞体)去撞击A,双方能受到碰撞事件。

    得出的结论似乎是如果碰撞双方只有一个有刚体,那么那个刚体一定要处于运动的状态下才会有碰撞事件发生。

    接下来就是IsTrigger选项了,上面的情况都没有触发信息,先列举一下触发事件和碰撞事件,如下:

    触发信息检测:
    1.MonoBehaviour.OnTriggerEnter( Collider other )当进入触发器
    2.MonoBehaviour.OnTriggerExit( Collider other )当退出触发器
    3.MonoBehaviour.OnTriggerStay( Collider other )当逗留触发器

    碰撞信息检测:
    1.MonoBehaviour.OnCollisionEnter( Collision collisionInfo ) 当进入碰撞器
    2.MonoBehaviour.OnCollisionExit( Collision collisionInfo ) 当退出碰撞器
    3.MonoBehaviour.OnCollisionStay( Collision collisionInfo )  当逗留碰撞器


    下面是一张关于触发的关系图,如下(注:同样是来自网上,我目前还没在官网上找着哈)

    下面就是我做的测试情况,都是A物体去撞B物体。

    一、A(碰撞体),B(没有碰撞体,无论有没有刚体),没有触发事件。

    二、A(碰撞体),B(碰撞体),没有触发事件。

    二、A(碰撞体和刚体,开启IsTrigger),B(碰撞体,关闭IsTrigger),双方都能收到触发事件。

    三、A(碰撞体和刚体,关闭IsTrigger),B(碰撞体,开启IsTrigger),双方都能收到触发事件。

    四、A (碰撞体,关闭IsTrigger),B(碰撞体和刚体,开启IsTrigger),没有触发事件。

    五、A (碰撞体,开启IsTrigger),B(碰撞体和刚体,关闭IsTrigger),没有触发事件。

    额外实验:

    六、A(碰撞体和刚体,开启IsTrigger)自由下落,B(碰撞体)撞击A,双方都能收到触发事件。

    根据上面的实验得出,如果要收到触发事件,必须满足如下三个条件:

    1、必须都要有碰撞器组件(Collider),其实上面的碰撞事件同样也需要这个前提条件。

    2、必须有一个物体带刚体组件,并且处于运动状体中(包括主动运动去撞击别人和在运动过程中被别人撞击)。

    3、两个碰撞器中至少有一个开启了IsTrigger。

    此外还有两点:

    一、产生触发事件的两个物体会相互穿越,准确的说是因为开启IsTrigger那个物体会被物理引擎锁忽略掉,所以会产生两个物体穿越的情况。

    二、两个对象要么都收到碰撞事件,要么都收到触发事件,不会出现一个收到触发事件,一个收到碰撞事件的情况。

    还有一个经验点就是,在控制一个物体A去撞另一个物体B时,不要直接去修改物体A的Transform的position属性,因为你会发现如果即使两者发生了碰撞也还是会穿越的,原因就在于我们是直接设置的坐标,如果物体A有刚体组件的话,应该用AddForce,给物体添加一个力,然后让物理引擎去让物体动,此时如果发生了碰撞的话,就不会穿越了。

    好吧,下午折腾了半天之后,我就一直在想那个IsTrigger有啥用,后来在网上搜了一下,说是可以做门的自动打开,就让我想起了Unity3d 4自带的哪个AngryBots例子,貌似当控制主角走到一个门前时,那个门会自动打开。

    于是就打开那个例子工程,去看,发现果然是这样的,大概原理就是在门前面放了一个设置了IsTrigger的透明碰撞体,用于专门监听碰撞,当主角进入这个区域时,就通过OnTriggerEnter事件把门预先打开。

    如图:

  • 相关阅读:
    IOS数据持久化之归档NSKeyedArchiver
    Java中导入、导出Excel
    IOS开发中多线程的使用
    深入分析动态管理Fragment
    IOS开发之数据sqlite使用
    如何在Eclipse和Tomcat的Debug过程中启用热部署
    在PHP中无法连接Memcached的解决办法
    Apache mod_rewrite规则重写的标志一览
    Java多线程中run(), start(), join(), wait(), yield(), sleep()的使用
    Centos5.8下编译安装PHP5.4和memcached, phalcon, yaf, apc
  • 原文地址:https://www.cnblogs.com/dabiaoge/p/4160888.html
Copyright © 2020-2023  润新知