Unity的使用(五):碰撞器和触发器

碰撞是游戏开发无法回避的一个话题,当我们的利刃划过敌人的躯体,子弹击中目标的头部,这些都是游戏物体和游戏物体之间的碰撞。那么我们怎么为我们想要的碰撞附加我们想要执行的事件函数呢?下面就为大家揭晓。

一. 碰撞器(Collider)

碰撞器(Collider)是组件,加了碰撞器的游戏物体才可能实现碰撞效果。在Unity内部提供了许多碰撞器,通过Add Component -> Physics可以添加3D碰撞器组件1。Unity提供的组件有:BoxCollider(盒碰撞器), SphereCollider(球碰撞器), CapsuleCollider(胶囊碰撞器), MeshCollider(网格碰撞器), WheelCollider(轮子碰撞器,用来创建交通工具), TerrainCollider(地形碰撞器), CharacterController(角色控制器)。

其中前三种为基元碰撞器,MeshCollider为常用碰撞器(后几种碰撞器有着特殊作用)。其中BoxCollider结构最简单,消耗最小,而MeshCollider最为复杂,消耗很高,且需要提供网格模型。

当两个碰撞体(Collider)发生了碰撞(Collision),且其中至少一个附加了刚体(Rigibody),会向它们附加的对象发射三条碰撞信息,可以在脚本里处理这些信息

//其中collision为本次碰撞信息集合,从中可以读取与之发生碰撞的碰撞体,碰撞的冲击力等信息
private void OnCollisionEnter(Collision collision) { }    //当两个碰撞体刚互相接触时
private void OnCollisionStay(Collision collision) { }    //当两个碰撞体持续保持接触状态时
private void OnCollisionExit(Collision collision) { }    //当两个碰撞体停止互相接触时

这里要详细介绍一下网格碰撞体(MeshCollider),其采用网格资源并基于该网格构建其碰撞体:
网格碰撞器的Inspector视图
碰撞网格使用背面剔除,如果对象与图形方式背面剔除的网格碰撞,则不会以物理方式与它碰撞(故两个网格碰撞体无法碰撞)。但若是该网格碰撞体标记为凸体(Convex),则可以和其它网格碰撞体发生碰撞,标记为凸体的网格碰撞体网格限制为255个三角形

二. 触发器(Trigger)

一个胶囊碰撞体
当我们需要检测游戏角色进入到某个房间里,这个时候你可能就会需要用到触发器了。触发器和碰撞器类似,碰撞器只需要将勾选上IsTrigger属性框就成了触发器。触发器发生碰撞时,同样会向它们附加的对象发射三条触发信息,不同的是其并不会发生物理碰撞效果。通过以下函数处理触发信息:

//其中collider为发生碰撞的碰撞体
private void OnTriggerEnter(Collider collider) { }    //当碰撞体进入到触发器时
private void OnTriggerStay(Collider collider) { }    //当碰撞体和触发器有重叠区域时
private void OnTriggerExit(Collider collider) { }    //当碰撞体离开触发器时

三. 刚体

刚体(Rigibody),为游戏对象赋予物理属性,使游戏对象实现现实世界中的运动效果的组件。刚体2是物理引擎中最基本的组件,通过刚体组件,可以为游戏物体添加一些常见的物理属性,如质量,摩擦力,碰撞参数等。
刚体概述
刚体的插值(Interpolate):物体运动插值模式,当发现刚体运动时抖动,可以尝试变换下面选项:

  • None: 无,不应用插值;
  • Interpolate: 内插值,基于上一帧Transform来平滑本帧Transform;
  • Extrapolate: 外插值,基于预测的下一帧Transform来平滑本帧Transform;

刚体的三种碰撞检测模式(CollisionDetection):

  • Discrete: 离散检测模式,普通默认状态,不适用于高速运动的物体,会有穿透的问题;尽量使用这一种;
  • Continuous: 连续检测,更加精细的碰撞检测,但是比较消耗性能;在这种状态下,此刚体与其它普通刚体碰撞时,仍使用Discrete的碰撞检测,与没有刚体的MeshCollider碰撞就会转为连续检测,防止穿过所有静态碰撞体;
  • Continuous Dynamic: 动态连续检测,对没有刚体的MeshCollider,和处在Continuous或ContinuousDynamic状态下的刚体使用连续碰撞检测,对其它刚体使用Discrete检测,防止对象穿过所有静态碰撞体及设置为Continuous或ContinuousDynamic的刚体。

四. 发生碰撞触发的条件

不是随随便便两个物体附加了碰撞体都可以发生碰撞,无论是发生碰撞还是触发都有一定的条件的。一般发生碰撞(触发),至少一方身上挂有刚体(Rigibody)。在了解发生条件之前,我们先要了解这几种碰撞体状态:

  1. Static Collider 静态碰撞器
    静态碰撞器是指一个包含碰撞器但不含刚体的游戏对象,这种游戏对象应当保持静止或很少移动。因此十分适用于环境几何结构,它们在与刚体发生碰撞时不会移动;
  2. Rigidbody Collider 刚体碰撞体
    是指同时包含了刚体和碰撞体的游戏物体,受物理引擎影响。
  3. Kinematic Rigidbody Collider 运动学刚体碰撞体
    此游戏对象同样包含有碰撞体和刚体,不同的是,它的刚体是运动学的(不受物理影响,只能直接设置)。适用于要经常四处移动的静态碰撞体,来发送触发器(Trigger)事件的情况。能够用来唤醒其它休眠的刚体。

则几种碰撞体相互之间碰撞触发的条件为:
碰撞体发生碰撞条件
触发器的触发发生条件:
触发器发生触发条件

附录:物理设置

默认情况下,碰撞体会和所有满足条件的碰撞体发生碰撞。但有些时候,我们希望某个碰撞体只和特定的碰撞体发生碰撞,这可以通过在Edit->ProjectSettings->Physics中设置。各个版本的Unity该选项的内容可能不同,建议根据Unity用户手册->Working in Unity->Editor Features->Project Settings->Physics中详细了解各个属性的作用。

这里以Unity2017的Physics为例:
设定物理属性面板
其中的各个属性为:

  • Gravity: 设定全局重力大小,需要注意的是,如果你增大了默认重力,最好同时增加DefaultSolverIterations值来维持稳定接触;
  • Default Material: 设置碰撞体的默认物理材质,当碰撞体没有分配物理材质时,将为其分配默认材质;
  • Bounce Threshold: 设置一个速度值,当两个碰撞体的相对速率小于这个值时,它们不会再弹开。这个值也用来减少抖动,因此不推荐设置的很小;
  • Sleep Threshold: 设置一个全局动能值,非运动学刚体动能小于这个值的将会进入休眠状态(不再每帧更新)以减小性能消耗;
  • Default Contact Offset: 设定碰撞检测系统判定发生碰撞时两个碰撞体间的最大的距离,这个值必须为正,且如果太过于接近零将造成抖动;
  • Default Solver Iterations: 定义在每个物理帧有多少个求解器(小型物理引擎,决定物理间的相互作用)运行。这将影响求解器输出的质量(当物理更新改变或有额外的需求时建议更改值),它可以减少由关节或接触产生的抖动;
  • Default Solver Velocity Iterations: 定义在每个物理帧有多少个求解器执行速度进程。这将影响刚体(碰撞后)反弹的准确性。当你需要获得具有多个刚体的游戏物体碰撞后的准确表现结果,尝试增加这个值;
  • Queries Hit Backfaces: 若被勾选,则允许对碰撞体的网格三角形执行背面检测(如从一个碰撞体内部发出的射线可以检测到该碰撞体);
  • Queries Hit Triggers: 若被勾选,则意味着物理检测(如射线)可以检测到触发器;
  • Enable Adaptive Force: 若被勾选,则采用适应力。当一个力作用于一整堆物体(如一整堆箱子)时,适应力能提供一个更真实的表现。
  • Enable PCM: 若被勾选,则启用Persistent Contacts Manifold方式生成碰撞;
  • Auto Simulation: 若被勾选,则自动运行物理模拟或允许对其直接控制;
  • Layer Collision Matrix: 层碰撞矩阵,其中的Water, UI等层就是在Edit->Project Settings->Tags And Layers中Layers里设定的层。打勾表示该行该列对应的两个层上的碰撞体可以发生碰撞,没有勾则表示对应的两个层上的碰撞体不能发生碰撞;

  1. 除了3D碰撞器,也有2D碰撞器,在Physics2D里。当我们进行2D游戏开发时,自然使用的就是2D碰撞器了,这里就不详细介绍了。 ↩︎

  2. 有2D碰撞器,自然也有2D刚体,为Rigidbody2D。 ↩︎

  • 10
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值