# 对 Unity 碰撞器的相关调研

1. 碰撞体与刚体 #

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

物体发生碰撞的必要条件 : 两个物体必须带有 Collider 碰撞器, 其中一个物体必须带有 Rigidbody 刚体. 在 Unity 中能检测到碰撞发生的方式有两种 : 利用碰撞器 或 利用触发器.

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

刚体 : 需要模拟重力的自由下落时, 添加刚体; 物体间发生碰撞时, 主动体身上必须添加刚体;

碰撞体 : 只有是碰撞体才能被射线检测到, 否则无法被检测; 碰撞体是产生碰撞的前提;

2. 碰撞器与触发器 #

碰撞器 : 一群组件, 有很多种碰撞体, 如 盒碰撞体 Box Collider,球形碰撞体,胶囊碰撞体,网格碰撞体 Mesh Collider,圆柱碰撞体等等. 位于 Unity 编辑器的 component>physics, 这些碰撞体应用的场合不同, 但是都必须加到 GameObject 身上.

触发器 : 只需要在检视面板中的碰撞器组件中勾选 IsTrigger 属性选择框.

触发信息检测 :

1
2
3
MonoBehaviour.OnTriggerEnter(Collider collider){} // 当进入触发器时
MonoBehaviour.OnTriggerExit(Collider collider){} // 当退出触发器时
MonoBehaviour.OnTriggerStay(Collider collider){} // 当逗留触发器时

碰撞信息检测 :

1
2
3
MonoBehaviour.OnColliderEnter(Collision collision){} // 当进入碰撞器时
MonoBehaviour.OnCollisionExit(Collision collision){} // 当退出碰撞器时
MonoBehaviour.OnCollisionStay(Collision collision){} // 当逗留碰撞器时

碰撞器和触发器的区别 :

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

  • 当 IsTrigger = false 没有勾选触发器的时候, 碰撞器根据物理引擎引发碰撞, 产生碰撞效果, 可以调用 OnColliderEnter/Exit/Stay 方法.
  • 当 IsTrigger = true 勾选了触发器的时候, 碰撞器被物理引擎忽略, 碰撞体之间谁也不让谁,相互僵持, 没有碰撞效果, 可以调用 OnTriggerEnter/Exit/Stay 方法.

特别地, 如果既要检测到物体的接触又不想让碰撞体碰撞影响到物体原本的移动 / 或想要检测一个物件是否经过空间中某个区域时, 可以使用触发器.

举例 : 汽车被撞飞, 皮球落地弹起使用碰撞器; 人站在靠近门的位置, 门自动打开使用触发器.

3. 实际开发的应用方式 #

实际开发中基本上只有两种情况

情况一 : 主动体(碰撞体 + 刚体) + 被动体(碰撞体) + 勾选 IsTrigger 属性 + OnTriggerXXX()
情况二 : 主动体(碰撞体 + 刚体) + 被动体(碰撞体) + OnColliderXXX()

4. 碰撞器的相关概念 #

静态碰撞器 Static Collider
没有附加刚体而附加了碰撞器的游戏对象. 这类对象会保持静止或很轻微的移动, 对于环境模型十分好用, 比如刚体和墙面碰撞的时候不会发生移动.

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

运动学刚体碰撞器 Kinematic Rigidbody Collider
附加了刚体和碰撞器, 在此基础上勾选激活了刚体组件中的 IsKinematic 属性, 移动这类对象, 只能修改它的 Transform, 而不是用力. 它们很像静态碰撞器不过对于想要不停地到处移动的碰撞器很好用, 这类游戏对象还有许多其他独特的使用情景.

这类对象可以用于你通常希望用静态碰撞器发出触发事件的情形下. 因为触发器必须要有刚体, 你应该添加刚体然后启用 IsKinematic, 这会阻止你的对象因物理作用而移动并且允许接收你希望得到的触发事件.

运动学刚体启用与否很容易控制, 这对创建人偶十分适用. 通常, 当你希望一个角色依照动画活动, 然后由于爆炸或者其他你选择的情况而引起的碰撞导致其变为人偶, 这种情况下, 很简单, 只需要通过脚本将运动学刚体改为普通刚体。

如果有刚体有时候变得静止不动了, 那么它们就是进入休眠了, 意味着它们将不受物理变化影响, 也就不会移动. 如果你把一个运动学的刚体从一个休眠的普通刚体的下边移走, 那休眠的刚体就会被唤醒并重新被物理变化时影响. 所以如果你有许多希望四处移动并有不同的对象要恰好砸到它们的静态碰撞器, 那就用运动学刚体碰撞器吧.

碰撞行为矩阵 Collision action matrix
基于两个碰撞对象的配置, 可以产生很多不同的效果. 有些组合只能导致碰撞的两个对象中的一个受到影响. 所以考虑到保持标准的规则 - 物理效果将不会对没有附加刚体的对象生效. 见表概括了基于附加不同组件的两个碰撞对象所产生的效果 → http://dev.gameres.com/Program/Unity3Dmanual/Components/class-BoxCollider.html

基于层的碰撞检测 Layer-Based Collision Detection
基于层的碰撞检测可以让你有选择地控制 Unity 对象和他们附加的特定层碰撞, 即在 GameObject 和绑定在指定层中的特定的 GameObject 之间进行碰撞检测.

碰撞器材质 Material
选择一种物理材质, 可以模拟更加真实的碰撞效果, 比如金属之间的碰撞与石头之间的碰撞效果必然是不一样的才对.

碰撞器中心点 Center
可以调整碰撞器离物体中心的距离, 也就是移动绿框.

碰撞器大小 Size
调整碰撞器的缩放大小, 调整 XYZ 可以让碰撞器变成任意大小的长方体.

碰撞器的类型
1.盒子碰撞器 Box Collider
盒碰撞器是一个基本的方形碰撞原型. 盒碰撞器可以被调整成不同大小的长方体, 能够很好地用于门、墙、平台等等. 也能够用于角色的躯干或者车辆等交通工具的外壳, 当然, 只是用在盒子或者箱子上表现也十分完美.

2.球形碰撞器 Sphere Collider
可以调整半径大小, 球形碰撞器在三维上可以均等地调节大小, 但不能只改变某一维(保持球体). 适合用于落石、乒乓球、弹球等等.

3.胶囊碰撞器 Capsule Collider
胶囊碰撞器由一个圆柱体连接两个半球体组成, 是一个同样形状的碰撞器原型. 可以调整半径,高度和方向, 即使是圆柱体也可以用这个做近似的碰撞的效果. 胶囊碰撞器的半径和高度都可以单独调节, 用于置于其两极间的角色控制器, 或者和其他碰撞器结合用于不规则的形状.

4.轮子碰撞器 Wheel Collider
可以调整虚拟质量, 半径高度, 悬浮距离, 弹力, 阻力等等参数. 主要用于附加在类似于轮胎这种对象上, 模拟驱动力的产生, 同时提供碰撞范围. 车轮碰撞器是一个特殊的地面车辆碰撞器, 它具有内置的碰撞检测、车轮物理引擎和一个基于滑移的轮胎摩擦模型. 当然, 它也可以用于其他对象, 但它是专门为有轮子的车辆设计.

车轮的碰撞检测, 通过自身 Y 轴的中心向下, 投射一条射线. 车轮有一个半径并可向下延伸, 相对于悬挂距离, 车轮从脚本使用不同的属性控制 : motorTorque(动力力矩), brakeTorque(制动力矩)和 steerAngle(转向角). 车轮碰撞器从物理引擎静止分开计算摩擦力, 使用基于滑动摩擦力模型. 这将得到更真实的行为, 但也导致车轮碰撞器忽略标准的物理学材质设置.

不转或滚 WheelCollider 物体来控制轿车, 附加 WheelCollider 的物体应始终相对轿车自身固定. 但是, 你可能想要转或滚图形轮, 要做到这一点的最好办法是分别设置物体的碰撞器和可见的车轮. http://www.ceeger.com/Components/class-WheelCollider.html

5.网格碰撞器 Mesh Collider
这是个强力的碰撞器, 用它能创造出不规则的碰撞范围, 但需要的性能消耗也比较大.

网格碰撞器利用一个网格资源并在其上构建碰撞器. 对于复杂网状模型上的碰撞检测, 它要比应用原型碰撞器精确的多. 标记为凸起的(Convex)的网格碰撞器才能够和其他网格碰撞器发生碰撞. 网格碰撞器通过附加在游戏对象上的网格构建碰撞效果, 并严格按照所附加对象的 Transform 属性来设定其位置和大小比例. 碰撞网格使用背面剔除(或译背面拣选,指正面多边形挡住了在它后面的背面多边形, Direct3D 将通过拣选(即删除多余的处理过程)背面多边形来提高效率的过程)如果一个对象和被背面剔除的网格碰撞, 那也不会在物理上碰撞. 使用网格碰撞器有一些限制条件. 通常, 两个网格碰撞器之间不会发生碰撞. 所有的网格碰撞器可以和任何原型碰撞器碰撞. 如果网格标记为凸起的(Convex), 那么就可以和其他网格碰撞器碰撞.

碰撞器作用于刚体使 Unity 中的物理作用生效, 因为刚体允许对象被物理系统控制, 碰撞器使对象之间产生碰撞作用. 碰撞器必须独立于刚体加在对象上, 碰撞器并不一定需要附加刚体,但是要使移动物体具有碰撞效果必须附加刚体。

几个重点 :

  • 除非被标记为凸起的(Convex), 否则网格碰撞器间不会发生碰撞. 因此, 它们最常被用于背景对象比如环境布景.
  • 凸起的网格碰撞器含有的三角形面不能多于255个.
  • 原型控制器对于对象的物理控制更加节省资源.
  • 当为游戏对象附加了网格碰撞器, 其网格属性将被定义为用于渲染的网格, 可以通过指派其他网格来改变.
  • 要给一个对象添加多个碰撞器, 应该创建子对象并给每个子对象添加一个碰撞器, 这使每个碰撞器可以被单独操作.
  • 可以通过场景视图(Scene View )中的线框(gizmos)来查看碰撞器在对象上的预期效果.
  • 碰撞器尽量匹配对象的比例, 如果有一组不规则伸缩(每一维度上的比例都不相同), 只能使用网格碰撞器才能完全匹配.
  • 如果你想接收通过 Transform 组件移动的对象的碰撞 / 触发信息,必须给移动对象附加刚体.

6.地形碰撞器 Terrain Collider
为什么我们的第一人称视角控制器不会从“地面”上往下坠?选中游戏中的地形对象, 就能发现它的身影.

5. 资料引用 #

https://zhidao.baidu.com/question/503212874.html
http://www.tuicool.com/articles/7b6Nbeq
http://blog.csdn.net/qq_15267341/article/details/58046029
http://www.narkii.com/club/thread-266478-1.html
http://bbs.9ria.com/thread-223673-1-1.html
http://www.ceeger.com/Components/class-MeshCollider.html

End.