[Unity 3D] Unity 3D 里的碰撞检测
Unity 3D里两个碰撞体之间发生碰撞可以用OnCollision族函数和OnTrigger族函数来获知和处理。Unity官方给出了两张可发生碰撞的组合表:
| 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 3D里的碰撞发生条件呢,归根结底只要理解了以下五个概念就搞定了:
Collider
Rigidbody
Static
Kinematic
Trigger
Collider——很简单,就是碰撞盒,有碰撞盒才有碰撞,所有碰撞的参与者都必须要有至少一个碰撞盒才行;
Rigidbody——刚体,当刚体存在时物理引擎就会介入,对于引擎来说,碰撞必须要有刚体参与(原因后述),但是并不要求碰撞的双方都是刚体,只要动的一方是刚体就OK,如果双方都有位移或者旋转,那么只要有一方是刚体就OK;
Static——这其实只是一个描述,或者说概念,任何不是刚体的物体,引擎都认为它永远是Static的,即静止的,哪怕它正在发生位移或者旋转;而刚体,引擎认为它是“能运动的”,也就是说,刚体虽然可以保持静止的状态,但是一旦发生位移或者旋转,引擎就会认为它动了;对于两个静止的物体,引擎认为他们不会发生碰撞,也就不会处理他们之间碰撞盒的任何交叠,这里包括两个非刚体,也包括一个保持静止的刚体和一个非刚体。这就是碰撞发生的双方中运动的那一方必须要是刚体的原因。
Kinemtic——这是一个描述,同时也是Rigidbody的一个属性。被标记为Kinematic的刚体就成为了一个纯运动学物体,这意味着它不再受外力作用,它的运动状态直接由位置和旋转来决定。当然,一个Kinematic的刚体还是可以对外产生作用力的,也就是说,它可以推动其他刚体,但是其他刚体对它无可奈何。
Trigger——这也是一个描述,同时是Collider的一个属性。被标记为Trigger的碰撞盒不再具备物理特性,这与Kinematic不一样,Kinematic的刚体仍就是一个物理体,而Trigger只代表一个区域,或是一个引子(这取决于它在碰撞中担当的角色,在碰撞中,如果它是运动的那一方,那么它就是一个引子,只要它碰撞到了任何物体,不论静止还是运动,都会被触发;如果它是静止的那一方,那么它就是一个区域,所有进入此区域的运动物体都会触发它,这里的“运动”不是单纯的位移或者旋转,参照Static的定义)。
好了,下面拿着这五个概念对照的看看Unity官方提供的表单。
先看Collision表,Collision是物理引擎管辖下的碰撞,即便是你不处理OnCollision族函数,物理引擎也会为碰撞双方计算作用力和作用力下的运行。由于Trigger标记下的物体不再是物理体,任何标记为Trigger的物体都不会触发Collision。物理碰撞的发生必然是有一方在运动,因此如果双方都被引擎认为是静止的物体,是不可能发生Collision的,因此双方都是非刚体(表中的Static Collider)时无法触发Collision。这里还有一个小问题,光从Collision表里是看不出来的,那就是在Static Collider和Rigidbody Collider之间,即便Collision表里画的是对钩,当碰撞里有位移或者旋转的那一方是Static Collider而不是Rigidbody Collider的时候,Collision是不会触发的哦,原因很简单,就是前面说的引擎认为物体静止的问题,没有位移或者旋转的Rigidbody是静止的,而非刚体也是静止的,两个静止的物体无法发生碰撞。至于Kinematic Rigidbody Collider,由于它本身不会受外力作用,而Collision是要能够产生物理作用力的,所以只有当能够受外力作用的物体跟它相撞时才会触发Collision,因此,没有作用力概念的Static Collider和不受外力作用的Kinematic Rigidbody Collider是无法跟它产生Collision的。
再看Trigger表,要触发Trigger就至少要有一个被标记为Trigger的碰撞盒存在,因此双方都没有被标记Trigger时,Trigger是不会触发的。即便有被标记为Trigger的物体存在,如果双方都被引擎认为是静止状态,同样不会触发Trigger(还是那个道理,两个被引擎认为静止的物体,是无法发生碰撞的),因此Static Collider跟Static Trigger Collider之间,两个Static Trigger Collider之间,都不会触发Trigger。跟Collision表一样,这里也有一个小问题光从表里看不出来,就是当Static Collider遇上Rigidbody(Kinematic)时,不管谁是Trigger,运动的一方必须要是Rigidbody(Kinematic)才能触发Trigger,道理同上。
唯一一个例外情况:
如果双方初始化在了一起,也就是说双方初始化出来碰撞盒就发生了交叠,这时候物理引擎网开一面,对于Collision来说,只要双方都不是Trigger,且有一方是非Kinematic的Rigidbody(也就是说Collision表里画了对钩的组合),就必然会发生一次Collision,对于Trigger来说,只要双方有一方是Trigger,且有一方是Rigidbody(Kinematic)(亚也就是Trigger表里画了对钩的组合),那么就必然会触发一次Trigger。当然这仅限初始化的那一帧,之后就一切回归正轨。
不过Unity 3D在这里有一个bug,当双方一个是非Kinematic的Rigidbody,另一方是Static Collider也就是非刚体,且碰撞盒在初始化时就交叠在了一起的话,除了一开始的那一帧会触发Collision外,之后刚体不动而非刚体动,仍有一定几率会触发Collision(按规则说是不能触发的),具体表现就是非刚体可以推着刚体走。
[Unity 3D] Unity 3D 里的碰撞检测的更多相关文章
- 关于Unity中的3D拾取
3D拾取 3D游戏实际上看到的是2D画面,我们在屏幕上点击,想要找到哪个3D物体,我们实际上是在一个2维平面内做3D拾取. 3D拾取实际上是,当玩家点击屏幕的时候,会从显示屏幕的摄像头发射一条射线,射 ...
- 如何用webgl(three.js)搭建一个3D库房,3D密集架,3D档案室(升级版)
很长一段时间没有写3D库房,3D密集架相关的效果文章了,刚好最近有相关项目落地,索性总结一下 与之前我写的3D库房密集架文章<如何用webgl(three.js)搭建一个3D库房,3D密集架,3 ...
- webgl(three.js)实现室内三维定位,3D定位,3D楼宇bim、实时定位三维可视化解决方案——第十四课(定位升级版)
序: 还是要抽出时间看书的,迷上了豆豆的作品,最近在看<天幕红尘>,书中主人公的人生价值观以及修为都是让我惊为叹止.很想成为那样的人,但是再看看自己每天干的事,与时间的支配情况,真是十分的 ...
- Ubuntu 11.10 安装GMONE3,卸载 UNITY和UNITY 2D
Ubuntu 11.10安装GNOME3: 1)sudo apt-get install gnome-shell sudo apt-get install gnome-themes* (或者 ...
- [Unity][安卓]Unity和Android Studio 3.0 交互通讯(1)Android Studio 3.0 设置
[安卓]Android Studio 3.0 JDK安卓环境配置(2017.10) http://blog.csdn.net/bulademian/article/details/78387052 [ ...
- Unity又称Unity Application Block
本文关注以下方面(环境为VS2012..Net Framework 4.5以及Unity 3): Ioc/DI简介: Unity简单示例 一.Ioc/DI简介 IoC 即 Inversion of C ...
- 如何用webgl(three.js)搭建一个3D库房,3D密集架,3D档案室,-第二课
闲话少叙,我们接着第一课继续讲(http://www.cnblogs.com/yeyunfei/p/7899613.html),很久没有做技术分享了.很多人问第二课有没有,我也是抽空写一下第二课. 第 ...
- Unity手册-Unity概述
Unity概述 Unity是一个强大引擎,他自带的多种工具可以满足你多种需求. 这种编辑器是直观的可定制的,让你的工作更大的自由. 原文 Unity is a powerful engine with ...
- 教你调节Boom 3D的3D音效强度,让音乐更带感
Boom 3D的专业3D环绕技术,让用户能全身心地沉浸在立体音效中.无论是聆听音乐,还是观赏电影,立体音效都能为人们带来更加真实的听觉感触. 那么,Boom 3D的3D环绕功能到底能给用户带来怎样的体 ...
- 如何用webgl(three.js)搭建一个3D库房,3D仓库,3D码头,3D集装箱可视化孪生系统——第十五课
序 又是快两个月没写随笔了,长时间不总结项目,不锻炼文笔,一开篇,多少都会有些生疏,不知道如何开篇,如何写下去.有点江郎才尽,黔驴技穷的感觉. 写随笔,通常三步走,第一步,搭建框架,先把你要写的内容框 ...
随机推荐
- AsyncSocket 使用
今天使用AsyncSocket模拟及时通信,在这里记录一下,免得以后自己又犯相同的错误 1>创建客户端和服务器socket /** * 设置socket */ - (void)setupSock ...
- iOS实战(零):开发社区、文档等资源
社区 Apple官方资源 Xcode文档库: Window->Documentation and API Reference (可以在xcode的Preferences中下载最新的文档) iOS ...
- 移动端纯原生JS不依赖ajax后台服务器实现省市县三级联动
最近好多天没有更新文章,是因为公司的项目忙的不行.今天有点时间,就突然想起在移动端项目中遇到三级联动的问题,网上查了很多资料,都是依赖各种插件,或者晦涩难于理解.于是,自己决定写一个出来. 当然,没有 ...
- PHP学习笔记7-JSON数据操作
JSON,全称是JavaScript Object Notation.它是基于JavaScript编程语言ECMA-262 3rd Edition-December 1999标准的一种轻量级的数据交换 ...
- PHP的排列组合问题 分别从每一个集合中取出一个元素进行组合,问有多少种组合?
首先说明这是一个数学的排列组合问题C(m,n) = m!/(n!*(m-n)!) 比如:有集合('粉色','红色','蓝色','黑色'),('38码','39码','40码'),('大号','中号') ...
- [转]IOS 中文排序
转自:http://www.cnblogs.com/syxchina/archive/2012/10/11/2720257.html 1 原因 Ios默认使用utf-8格式编码,所以中文在IOS中默认 ...
- 自定义Chrome 背景色 (FF需要User Styles插件)
Chrome有个自定义背景色的文件 Custom.css 默认里面什么字都没写 html, body {background-color: #e0dcc0!important;} 这个颜色 ...
- discuz默认模板文件结构详解-模板文件夹介绍
| — template — default 系统内置风格模板(默认风格)| — template — default – discuz_style_default.xml 风格安装文件,可用 ...
- 在cnblog中使用syntax方法
<pre name="code" class="brush: cpp;"> 代码 </pre> #include<cstdio&g ...
- Libev学习笔记1
和Libevent相似,Libev是一个高性事件驱动框架,据说性能比Libevent要高,bug比Libevent要少.Libev只是一个事件驱动框架,不是网络库,因为它的内部并没有任何socket编 ...