码迷,mamicode.com
首页 > 编程语言 > 详细

碰撞器与触发器[Unity]

时间:2015-02-13 19:52:39      阅读:17960      评论:0      收藏:0      [点我收藏+]

标签:

请看原帖,移步:Unity3d碰撞检测中碰撞器与触发器的区别

  要产生碰撞必须为游戏对象添加刚体(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函数。
 
  如果既要检测到物体的接触又不想让碰撞检测影响物体移动或要检测一个物件是否经过空间中的某个区域这时就可以用到触发器
 
例子:
  碰撞器:汽车被撞飞、皮球掉在地上又弹起效果
  触发器:人站在靠近门的位置门自动打开效果
 
另外,collider的性能和效率大概的顺序是:Sphere Collider > Capsule > Box Collider > Mesh Collider.
 

  碰撞器是另一种组件,它和刚体一起,来使碰撞发生。如果两个刚体撞在一起,物理引擎将不会计算碰撞除非它们包含一个碰撞器组件。没有碰撞器的刚体,会在物理模拟中相互穿透。碰撞器必须独立于刚体加在对象上。碰撞器并不一定需要附加刚体,但是要使移动物体具有碰撞效果必须附加刚体。为了使两个触发器碰撞时发出碰撞事件,其中一个必须包含刚体。

技术分享
通过菜单Component->Physics menu来添加一个碰撞器。

Box Collider盒碰撞器--基本形状是个盒子。

Sphere Collider 球碰撞器--基本形状是个球。

Capsule Collider 胶囊碰撞器--基本形状是个胶囊。

Mesh Collider 网格碰撞器--从物体的网格创建一个碰撞器。不能与其他网格碰撞器相碰撞。

Wheel Collider 轮碰撞器--特殊的碰撞器,用于创建车或其他移动交通工具。

碰撞器属性:

Material 材质

Is Trigger 是否触发器

Radius 半径

Center 中心

Size 大小 在X、Y、Z三维上的碰撞器尺寸。

Mesh 网格

Smooth Sphere Collisions 平滑性状碰撞 当被激活,碰撞网格法线是平滑的。用于平滑表面比如由没有棱角的平滑起伏组成的起伏地表时应该激活。

Convex 凸起的 如激活,该网格碰撞器将会和其他网格碰撞器碰撞。凸起的网格碰撞器限制在255个三角形面内。

胶囊碰撞器的半径和高度都可以单独调节。用于置于其两极间的角色控制器,或者和其他碰撞器结合用于不规则的形状。

技术分享

 

当你有一个复杂网格却不适用网格碰撞器的情况下,使用组合碰撞器是个好的选择。要创建组合碰撞器,先为你的碰撞物体创建子对象,然后对每个子对象创建一个基本碰撞器。这样就允许你轻易的独立移动、旋转和放缩每个碰撞器。

网格碰撞器之间通常不相互碰撞,但如果一个网格碰撞器被标记为凸起的(Convex ),那么它就可以与其他网格碰撞器碰撞。典型的解决方案是,对移动的对象使用基本碰撞器,而对静态环境对象使用网格碰撞器。

碰撞网格使用背面剔除(或译背面拣选,指正面多边形挡住了在它后面的背面多边形,Direct3D将通过拣选(即删除多余的处理过程)背面多边形来提高效率的过程。)如果一个对象和被背面剔除的网格碰撞,那也不会在物理上碰撞。

Static Colliders 静态碰撞器

一个静态碰撞器是一个包含碰撞器但不含刚体的游戏对象。静态碰撞器用于总是待在同一个地方不移动的水平几何体。你能把一个网格碰撞器添加到已存在的图形网格(甚至比用输入设置产生碰撞器复选框好用),或者你可以使用了另一种碰撞器类型。

你不要逐帧移动 一个静态碰撞器,移动静态碰撞器将导致PhysX引擎的内部重置,非常耗费资源,而且会造成性能的极大下降。另外,基于一个静态碰撞器唤醒其他刚体的行为 是未定义的,而且移动静态碰撞器将不会对碰到它的刚体施加摩擦力。取而代之的是,要移动的碰撞器要保持是运动学刚体。

  Layer-Based Collision Detection 基于层的碰撞检测

在Unity3以后版本,我们介绍了一种称为“基于层的碰撞检测”(Layer-Based Collision Detection)的东西,可以让你有选择地控制Unity对象和他们附加的特定层碰撞。

选择选定游戏对象的层.

技术分享

 

Edit->Project Settings->Physics.,打开物理引用界面. 在碰撞矩阵中选择要与其他层相互作用的层,勾选即可.

技术分享

 

另外,看下有人做的物理碰撞实验:【Unity】物理碰撞实验

文中提到Unity组件文中将碰撞体分为3个类型:

Static Collider 静态碰撞器

These are GameObjects that do not have a Rigidbody attached, but do have a Collider attached. These objects should remain still, or move very little. These work great for your environment geometry. They will not move if a Rigidbody collides with them.

指的是没有附加刚体而附加了碰撞器的游戏对象。这类对象会保持静止或者很轻微的移动。对于环境模型十分好用,当和刚体碰撞时而不会移动。 

Rigidbody Collider 刚体碰撞器 

These GameObjects contain both a Rigidbody and a Collider. They are completely affected by the physics engine through scripted forces and collisions. They might collide with a GameObject that only contains a Collider. These will likely be your primary type of Collider in games that use physics.

指的是同时附加了刚体和碰撞器的游戏对象。通过脚本的力量和碰撞完全受物理引擎的影响。可以和只包含碰撞器的游戏对象碰撞。将会成为你游戏中使用物理效果的基本类型碰撞器。 

Kinematic Rigidbody Collider 运动学刚体碰撞器

This GameObject contains a Collider and a Rigidbody which is marked IsKinematic. To move this GameObject, you modify its Transform Component, rather than applying forces. They‘re similar to Static Colliders but will work better when you want to move the Collider around frequently. There are some other specialized scenarios for using this GameObject.

指的是同时包含碰撞器和刚体,并且激活IsKinematic的一类游戏对象,要移动这类游戏对象,要修改它的Transform组件(指的是position和rotation这类属性),而不是用力。它们很像静态碰撞器,不过如果你想要不停地到处移动碰撞器,它们会更好用。这类游戏对象还有许多其他的独特使用情景。

运动学刚体碰撞器是个非常懒惰和霸道的家伙,它碰到其他碰撞器完全没有反应(其实还是有点反应,会触发一些碰撞函数的,后面有解释)。它不受力、重力或扭矩的影响。可以通过设置Transform 的position和rotation来准确的操作它们或者让它们动起来,但是,它们可以和其他的非运动学刚体互相作用。对于放在运动学刚体碰撞器上面的刚体,会受到运动学刚体施加的摩擦力。

 

还有一类叫做角色控制器。

Character Controllers 角色控制器

You use Character Controllers if you want to make a humanoid character. This could be the main character in a third person platformer, FPS shooter or any enemy characters.

如果想制作一个类似人的角色那就使用角色控制器。这可以是第三人称平台游戏、第一人称射击游戏的主要角色或任何敌对角色。

These Controllers don‘t follow the rules of physics since it will not feel right (in Doom you run 90 miles per hour, come to halt in one frame and turn on a dime). Instead, a Character Controller performs collision detection to make sure your characters can slide along walls, walk up and down stairs, etc.

这类控制器不遵循物理规则因此它感觉上不对劲(在Doom中,你跑到了90英里每小时,然后马上停下而且可以极快的转身)。不过,角色控制器执行碰撞检测以保证你的角色可以沿着墙滑动,上下台阶等等。

Character Controllers are not affected by forces but they can push Rigidbodies by applying forces to them from a script. Usually, all humanoid characters are implemented using Character Controllers.

角色控制器不受力影响(但是重力效果还是有的)但是可以被由代码施加的力推动。通常,所有类似人的角色都用角色控制器来执行。

Character Controllers are inherently unphysical, thus if you want to apply real physics - Swing on ropes, get pushed by big rocks - to your character you have to use a Rigidbody, this will let you use joints and forces on your character. Character Controllers are always aligned along the Y axis, so you also need to use a Rigidbody if your character needs to be able to change orientation in space (for example under a changing gravity). However, be aware that tuning a Rigidbody to feel right for a character is hard due to the unphysical way in which game characters are expected to behave. Another difference is that Character Controllers can slide smoothly over steps of a specified height, while Rigidbodies will not.

角色控制器本身不具物理特性,因此如果想应用真正的物理作用——在绳上摇摆,被大石头推动——到你的角色,必须用刚体,这会允许你把铰链或力用到你的角色上。角色控制器永远沿Y轴对齐,因此,如果你的角色需要在空间中改变方向那也必须用到刚体(比如在变化的引力控制下)。但是,要意识到调整一个刚体在角色上表现自然是很难的,因为游戏角色自身的非物理特性总想表现出来。另一个困难是,角色控制器可以从特定高度的台阶上平滑地滑下,而刚体不会。

 

The Controller does not react to forces on its own and it does not automatically push Rigidbodies away.

控制器不会对加在它自身上的力做出反应,也不会自动推开其他刚体。(这里我没有明白,因为我实验过在一个刚体内部实例化一个控制器,刚体是会被弹开的。如果有人懂请告诉我,不胜感激!)

If you want to push Rigidbodies or objects with the Character Controller, you can apply forces to any object that it collides with via the OnControllerColliderHit() function through scripting.

如果想让角色控制器推开其他刚体或者对象,你可以在对象附加的脚本中添加OnControllerColliderHit()函数,这样对它们施加力就能够产生碰撞。

也就是说,角色控制器可以使用物理效果影响其他对象,前提是你自己写了脚本。

On the other hand, if you want your player character to be affected by physics then you might be better off using a Rigidbody instead of the Character Controller.

而角色控制器不能通过物理效果被其他对象影响。因此,如果你想让你的游戏角色被物理效果影响,那就最好使用刚体而不是角色控制器。

 

角色控制器和运动学刚体有点像,因为它们都不受力的作用(运动学刚体更像是一个刚体,只是不会受到其他任何外力的影响,就像是古代的国王,虽然和普通平民一样都是人,但是只能他欺负别人,别人无法欺负他;而角色控制器本身就不具有物理特性,不可以推开别人(除非写了自己的脚本),也不会被别人影响,只是它可以执行碰撞检测)。但是也有几点不同的地方。首先,运动学刚体是无法通过代码施加力的作用来推动,但是角色控制器是可以的。第二,运动学刚体不会受到重力的作用,而角色控制器是有重力效果的。其次,角色控制器只能沿Y轴旋转,也就是人永远都是直立状态,不会因为受到力的作用就趴下啦,而刚体是可以的。第三,角色控制器可以从特定高度台阶上平滑地滑下,而刚体不会。

说了这么多,晕了吧,恩,我也晕了。所以我们来做下实验!我们通过一个最简单的场景,即一个平行光、一个平面、两个正方体来试验一下。通过给两个正方体添加不同的碰撞体类型来观察是否会发生碰撞。

技术分享

下面的实验中,一个正方体保持静止,另一个正方体我们通过代码来控制运动,即上下左右方向键可以控制它的上下左右运动。

 

 

移动的静态碰撞器VS静止的静态碰撞器

没有任何碰撞效果。这在意料之中,因为没有一个添加了Rigdbody属性,肯定不会碰撞啦!
 
 

移动的静态碰撞器VS静止的刚体碰撞器

没有任何碰撞效果。
这个结果有点意外,明明一个已经添加了Rigdbody,为什么还是无法发生碰撞呢?这是因为添加了Rigdbody的正方体是静止的,而静止的刚体会进入休眠。好吧,又遇到了新的名词, 刚体休眠。例如,当一个正方体掉到地板上静止后就会进入刚体休眠。刚体休眠完全自动发生。只要刚体的速度低于sleepAngularVelocity和sleepVelocity,该刚体就会开始休眠。其空闲一些帧后,就会被设置成休眠状态。处于休眠状态中的物体,不会再对其进行碰撞检测和模拟。这会节约大量的CPU开销。这就解释了为什么我们这个实验里没有碰撞发生,因为它睡觉去了,而那个移动的静态碰撞器又无法唤醒它,所以它压根就不知道有人碰到了自己。这里又有一个问题了,那么什么情况下可以唤醒已经休眠了的刚体呢?有4中情况:
  • 被施加了外力,也就是说在代码里使用了AddForce;
  • 刚体的属性发生了变化;
  • 和它通过关节连接的刚体发生了移动,因为连带关系,所以它也被唤醒了;
  • 被其他刚体碰撞器碰撞。但是,只有处于运动状态中的刚体(包括普通的刚体碰撞器和运动学刚体碰撞器)能唤醒休眠中的刚体,静态碰撞器不能唤醒休眠中的刚体。即如果你将一个静态碰撞器(没有和任何刚体绑定过)绑定到处于休眠中的刚体,或者将静态碰撞器抽离处于休眠中的刚体时,这个休眠中的刚体是不会被唤醒的。但是如果你将一个运动中的刚体从它所属的且处于休眠状态中的顶层刚体移出时,处于休眠中的刚体将会被唤醒,且会在图形更新里被重新正确的计算。
最后这句话时什么意思呢?我们再做两个实验好了。还是两个正方体,我们将一个正方体放在另一个的上方。
技术分享 
在两个实验里,上方的正方体都是普通的刚体碰撞器,而下方的正方体有所不同,我们可以通过代码移动下方的正方体使得它从上方正方体的下面移开。
第一个实验里,下方的正方体是一个静态碰撞器。当我们移开后,上方的正方体直直地下落,直到碰到地板,期间没有任何物理效果(除了重力效果)。
第二个实验里,下方的正方体是一个运动学刚体碰撞器。当我们移开下方正方体的过程中,我们会发现上方的正方体会受到摩擦力的左右而也发生了一定移动,当两个正方体完全分离后,上方的正方体晃动着掉到了地板上(因为之前受到了摩擦力)。
好了,有点明白了吗?静态碰撞器是不会唤醒休眠刚体的(第一个实验),而运动学刚体由于会对刚体产生力的作用而可以唤醒休眠中的刚体。
 
再提一个问题,如果上面的正方体是运动学刚体碰撞器呢?那么无论下面是什么碰撞器它都没有反应,因为它是国王啦,不受到任何外力的影响,包括重力!
 
 

移动的刚体碰撞器VS静止的静态碰撞器

有碰撞效果,具体为:对于移动的刚体碰撞器在遇到静态碰撞器后会产生物理效果,如反弹、无法前进等;对于静止的静态碰撞器,会产生轻微的碰撞效果,如轻微的晃动,但是不会移动。
 
 

移动的刚体碰撞器VS静止的刚体碰撞器

有碰撞效果,对于两个物体都出现正常的物理效果,如反弹等。
 
 

移动的静态碰撞器VS静止的运动学刚体碰撞器

没有任何碰撞效果。运动学刚体碰撞器是不受到任何外力作用的。
 
 

移动的运动学刚体碰撞器VS静止的静态碰撞器

没有任何碰撞效果。运动学刚体碰撞器是不受到任何外力作用的。
 
 

移动的运动学刚体碰撞器VS静止的刚体碰撞器

有碰撞效果,但仅刚体碰撞器有碰撞效果,如反弹等,运动学刚体碰撞器不受力的作用。
 
 

移动的刚体碰撞器VS静止的运动学刚体碰撞器

有碰撞效果,但仅刚体碰撞器有碰撞效果,如反弹等,运动学刚体碰撞器就像一堵墙一样一动不动。
 
 

移动的运动学刚体碰撞器VS静止的运动学刚体碰撞器

两个太上皇相见了会怎么样呢?没有任何反应……就像两个静态碰撞器一样。
 
 
 
下面,将一个正方体换成角色控制器,继续实验。
技术分享 
 
 

移动的静态碰撞器VS静止的角色控制器

没有任何碰撞效果。
 
 

移动的刚体碰撞器VS静止的角色控制器

有碰撞效果,刚体碰撞器遇到角色控制器后会发生反弹,无法继续前进,而角色控制器没有任何效果。
 
 

移动的运动学刚体碰撞器VS静止的角色控制器

没有任何碰撞效果,会互相穿过。
 
 

移动的角色控制器VS静止的静态碰撞器

没有任何碰撞效果,会互相穿过。 
 
 

移动的角色控制器VS静止的刚体碰撞器

有碰撞效果,刚体碰撞器被弹开。
 
 

移动的角色控制器VS静止的运动学刚体碰撞器

没有任何碰撞效果,会互相穿过。 
 
 
 

碰撞信息和触发信息

 
对于碰撞时是否会发出碰撞函数(或触发信息),可以见下表。碰撞信息是指OnCollisionEnter() OnCollisionStay()和 OnCollisionExit()这三个函数,而触发信息指的是OnTriggerEnter() OnTriggerStay和OnTriggerExit()三个函数。
 
 
Collision detection occurs and messages are sent upon collision
碰撞后有碰撞检测并有碰撞信息发出
  Static Collider
静态碰撞器
Rigidbody Collider
刚体碰撞器
Kinematic 
Rigidbody Collider
运动学刚体碰撞器
Static 
Trigger Collider
静态触发碰撞器
Rigidbody 
Trigger Collider
刚体触发碰撞器
Kinematic Rigidbody 
Trigger Collider
运动学刚体触发碰撞器
Static Collider 静态碰撞器   Y        
Rigidbody Collider 刚体碰撞器 Y Y Y      
Kinematic Rigidbody Collider 
运动学刚体碰撞器
  Y        
Static Trigger Collider
静态触发碰撞器
           
Rigidbody Trigger Collider
刚体触发碰撞器
           
Kinematic Rigidbody Trigger Collider
运动学刚体触发碰撞器
           
Trigger messages are sent upon collision
碰撞后有触发信息
  Static Collider
静态碰撞器
Rigidbody Collider
刚体碰撞器
Kinematic 
Rigidbody Collider
运动学刚体碰撞器
Static 
Trigger Collider
静态触发碰撞器
Rigidbody 
Trigger Collider
刚体触发碰撞器
Kinematic Rigidbody 
Trigger Collider
运动学刚体触发碰撞器
Static Collider 静态碰撞器         Y Y
Rigidbody Collider 刚体碰撞器       Y Y Y
Kinematic Rigidbody Collider
运动学刚体碰撞器
      Y Y Y
Static Trigger Collider 静态触发碰撞器   Y Y   Y Y
Rigidbody Trigger Collider
刚体触发碰撞器
Y Y Y Y Y Y
Kinematic Rigidbody Trigger Collider
运动学刚体触发碰撞器
Y Y Y Y Y Y

技术分享

碰撞器与触发器[Unity]

标签:

原文地址:http://www.cnblogs.com/slysky/p/4290803.html

(1)
(10)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!