好久没写帖子了,最近忙于个人私事与工事间的徘徊,so...,在此感谢大家一直以来对我的关注与支持,谢谢!!!
好了,就不多废话了,直接进入今天主题。
最近总有人问我 unity 3d中碰撞检测到底怎么做?什么时候该用触发信息检测碰撞?什么时候又该用碰撞信息检测碰撞?它们之间有什么区别?等等...ok,让我们带着上边疑问一起一探究竟吧。
首先,我们简单来了解下碰撞的定义: 如果两个或几个物体再相遇中,物体之间的相互作用力仅持续一个极为短暂的时间,这些现象就是碰撞。
由上可见,要产生碰撞信息必须满足2个以上的对象物体,其中一个一定包含”力“。
那么在unity,它又所需什么样的条件?
其实,在unity中我在此总结有3种方式8种方法,分别为:
1.通过触发器信息检测碰撞
1).OnTriggerEnter( Collider other )进入触发器
2).OnTriggerExit( Collider other )退出触发器
3).OnTriggerStay( Collider other )停留触发器
2.通过碰撞信息检测碰撞
4).OnCollisionEnter( Collision collisionInfo ) 进入碰撞器
5).OnCollisionExit( Collision collisionInfo ) 退出碰撞器
6).OnCollisionStay( Collision collisionInfo ) 停留碰撞器
3.通过Ray射线检测碰撞(感觉又不属于碰撞范畴,但是它又具有这样的功能,因此暂且归纳)
7).static function Raycast (origin : Vector3, direction : Vector3, distance : float = Mathf.Infinity, layerMask : int = kDefaultRaycastLayers) : bool
8).LayerMask层级检测
好了,我们知道了有这么多种在unity中检测碰撞的方式及方法,可是如何去使用呢?
so,我们有必要稍微了解下它们的基本概念:
1.碰撞器:在unity中,所谓的 碰撞器其实是一些组件 ,同时包含了Box Colloder(盒子状)、Sphere Collider(球形)等,如图
2.触发器:在unity中,是建立在碰撞器基础上的,也就是在 碰撞器的属性面板中勾选IsTrigger选择框 即可,如图
3.Ray射线:它不是Unity特有的东西,至于还有那些地方应用,在此我就不过多描述,不在业务范围内,有兴趣的可以自行去研究下。
在unity中它是 由一个点向一个方向发射的一条无终点的线,在发射轨迹中与其他物体发生碰撞时,它将停止发射 。
因此在unity中应用还是非常广泛的,通常能快速解决一些棘手的 问题 ,如:点击屏幕移动角色,在3维空间中不使用控件的前提下,点击选中某个对象等等...如图
ok,上面我们基本了解了各种方式的基本概念,下面举个列子详细讲解下。
新建一个场景,在此名字为test,加一个平行光,然后依次创建cube、Capsule、Sphere 三个对象,接着继续创建3个材质球( Material ),
分别为cube Material、 Capsule Material 、Sphere Material并给3种不同颜色:红、黄、蓝 。建好如下图
1.创建代码TriggerTest ,如下
代码写好后,绑定脚本到红色Cube上运行,手动在Scene拖动任意其他对象去跟Cube碰撞,尴尬的事情来了,居然没有任何反应
这是什么情况?嘿嘿,看来我们还得完善下unity中有关碰撞器方面的知识啊,以下来自圣典翻译文档(蛮牛不会认为我打广告吧,为学东西拼啦)
Static Collider 静态碰撞器、 Rigidbody Collider 刚体碰撞器、 Kinematic Rigidbody Collider 运动学刚体碰撞器这三种为常用类型,
其中, 这三种碰撞器如果勾选了IsTrigger复选框,就变成了相应的触发器。
还有个 表里面包含了检测到碰撞信息所必要的碰撞组合,总结很到位
从表中可以看出,两个碰撞器要想检测到碰撞信息,至少有一个是Rigidbody Collider。这个就是我们刚才失败的关键
原来还有一个东西我们忘记了,那就是 Rigidbody(钢体) ,ok,我们给红色的cube 加上钢体,去掉Use Gravity勾选,这里
我们不需要使用重力,运行,移动黄色胶囊去碰撞红色cube
ok,是我们想要的结果。
简要终结下: 两个GameObject发生碰撞,要想检测到触发信息,最少要有一个刚体碰撞器并且勾选了IsTrigger复选框,另一个最少要有一个碰撞器组件,此时检测碰撞的脚本必须附加在那个带有刚体的触发器上。
可是,后面自己又测试一番下来 发现一个很奇怪的问题,触发器一直是红色Cube
1.我把钢体绑定到其他物体上,运行结果,只有cube去撞其他物体才能触发,手动拖动其他物体不触发。
2.接着我把脚本放到其他物体上,运行结果同上。
3.然后我把脚本放到其他物体上,钢体放红色Cube上,运行结果,只有手动拖动其他物体去撞cube触发,拖动cube去撞其他物体不触发。
剩下的 通过碰撞信息检测碰撞大家自行研究,在此我就不过多叙述,基本跟上同理,只不过不勾选Is Trigger就可以了,代码方法都换成 OnCollision xxx 的就可以了,不要忘记里面参数也要换 Collision collisionInfo 。
最后大家可能会问,着2种都是碰撞检测 在什么情况下用哪个呢?
我只说 使用Collision碰撞信息检测碰撞 是属于物理碰撞,如何使用 就看大家使用时是否需要具有物理特性碰撞了,没有就用Trigger触发保险点。
这里是圣殿的翻译文档地址也给大家,方便查看 :http://game.ceeger.com/Components/class-MeshCollider.html
接下来就是Ray射线检测及关于 layerMask的使用 ,这块在我前面帖子有专门的讲解【 unity射线碰撞检测+LayerMask的使用 】大家可以看下。
其实,这里我最想说的是关于Physics.Raycast()的用法,以前其实我自己都没注意这块,今天无意间发现原来里面还有这么多方便使用的函数
其中,包括 通过范围来查找怪物 等等,下面奉上 Physics.xx 函数方法
1) static function Raycast (origin : Vector3 , direction : Vector3 , distance : float = Mathf.Infinity , layerMask : int = kDefaultRaycastLayers) : bool
在origin坐标上建立一个方向为direction,距离为distance的射线,可以与layerMask(层遮罩)之外的所有的collider碰撞;
返回true如果碰撞到任何物体,否则返回false。 distance默认为无限远,layerMast默认为kDefaultRaycastLayers
只与第一个接触到的物体产生碰撞。
static function Raycast (origin : Vector3 , direction : Vector3 , out hitInfo : RaycastHit , distance : float = Mathf.Infinity , layerMask : int = kDefaultRaycastLayers) : bool
多了一个out hitInfo: RaycastHit, 如果碰撞到物体,具体碰撞数据和被碰撞体都会被记录在RaycastHit上,包括碰撞位置,碰撞位置法线,被碰撞体的Transform节点等信息。其他一样。
脚本:
var explosionPosition: Vector3;
var hit: RaycastHit;
if(Physics.Raycast(transform.position,target.position,hit,100)){
explosionPosition=hit.point;
}
static function Raycast (ray : Ray , distance : float = Mathf.Infinity , layerMask : int = kDefaultRaycastLayers) : bool
static function Raycast (ray : Ray , out hitInfo : RaycastHit , distance : float = Mathf.Infinity , layerMask : int = kDefaultRaycastLayers) : bool
直接由一个射线ray来指示位置和方向。其他一样。
2) static function RaycastAll (ray : Ray , distance : float = Mathf.Infinity , layerMask : int = kDefaultRaycastLayers) : RaycastHit []
static function RaycastAll (origin : Vector3 , direction : Vector3 , distance : float = Mathf.Infinity , layermask : int = kDefaultRaycastLayers) : RaycastHit []
与所有在ray这条射线上的物体碰撞并返回所有被碰撞体,RaycastHit[]。 其他同RaycastAll一样。
3)static function Linecast ( start : Vector3 , end : Vector3 , layerMask : int = kDefaultRaycastLayers) : bool
static function Linecast ( start : Vector3 , end : Vector3 , out hitInfo : RaycastHit , layerMask : int = kDefaultRaycastLayers) : bool
从start到end画一条直线,其他与Raycast和RaycastAll类似。 这个通常可以用于检测AI是否能看到目标物体等功能。
4) static function OverlapSphere (position : Vector3 , radius : float , layerMask : int = kAllLayers) : Collider []---可用于检查范围内的怪物
检测在position位置的半径radius的球形范围内是否存在可碰撞体并返回所有检测到的collider
5) static function CheckSphere (position : Vector3 , radius : float , layerMask : int = kDefaultRaycastLayers) : bool
当任何物体碰到position位置的半径为radius的球形范围时返回true;
6) static function CheckCapsule ( start : Vector3 , end : Vector3 , radius : float , layermask : int = kDefaultRaycastLayers) : bool
当任何物体碰到定义的胶囊体范围时返回true;
7) static function IgnoreCollision (collider1 : Collider , collider2 : Collider , ignore : bool = true) : void
控制collider1和collider2 是否可以碰撞。 ignore=true 两者将不会计算是否碰撞, ignore=false 则计算两者是否有碰撞。
原文地址:http://www.cnblogs.com/tonge/p/3614414.html 是不是挺有用?那还不赶快动手尝试下?
好了,就不多废话了,直接进入今天主题。
最近总有人问我 unity 3d中碰撞检测到底怎么做?什么时候该用触发信息检测碰撞?什么时候又该用碰撞信息检测碰撞?它们之间有什么区别?等等...ok,让我们带着上边疑问一起一探究竟吧。
![](http://www.unitymanual.com/static/image/smiley/default/20119012.gif)
首先,我们简单来了解下碰撞的定义: 如果两个或几个物体再相遇中,物体之间的相互作用力仅持续一个极为短暂的时间,这些现象就是碰撞。
由上可见,要产生碰撞信息必须满足2个以上的对象物体,其中一个一定包含”力“。
那么在unity,它又所需什么样的条件?
其实,在unity中我在此总结有3种方式8种方法,分别为:
1.通过触发器信息检测碰撞
1).OnTriggerEnter( Collider other )进入触发器
2).OnTriggerExit( Collider other )退出触发器
3).OnTriggerStay( Collider other )停留触发器
2.通过碰撞信息检测碰撞
4).OnCollisionEnter( Collision collisionInfo ) 进入碰撞器
5).OnCollisionExit( Collision collisionInfo ) 退出碰撞器
6).OnCollisionStay( Collision collisionInfo ) 停留碰撞器
3.通过Ray射线检测碰撞(感觉又不属于碰撞范畴,但是它又具有这样的功能,因此暂且归纳)
7).static function Raycast (origin : Vector3, direction : Vector3, distance : float = Mathf.Infinity, layerMask : int = kDefaultRaycastLayers) : bool
8).LayerMask层级检测
好了,我们知道了有这么多种在unity中检测碰撞的方式及方法,可是如何去使用呢?
so,我们有必要稍微了解下它们的基本概念:
1.碰撞器:在unity中,所谓的 碰撞器其实是一些组件 ,同时包含了Box Colloder(盒子状)、Sphere Collider(球形)等,如图
![](http://www.unitymanual.com/data/attachment/forum/201410/13/114119waqzv9aavvgg9vcz.jpg.thumb.jpg)
2.触发器:在unity中,是建立在碰撞器基础上的,也就是在 碰撞器的属性面板中勾选IsTrigger选择框 即可,如图
![](http://www.unitymanual.com/data/attachment/forum/201410/13/114608aqr9ren2zndzllny.jpg.thumb.jpg)
3.Ray射线:它不是Unity特有的东西,至于还有那些地方应用,在此我就不过多描述,不在业务范围内,有兴趣的可以自行去研究下。
在unity中它是 由一个点向一个方向发射的一条无终点的线,在发射轨迹中与其他物体发生碰撞时,它将停止发射 。
因此在unity中应用还是非常广泛的,通常能快速解决一些棘手的 问题 ,如:点击屏幕移动角色,在3维空间中不使用控件的前提下,点击选中某个对象等等...如图
![](http://www.unitymanual.com/data/attachment/forum/201410/13/143308vtgv82m7x818b7xt.jpg.thumb.jpg)
ok,上面我们基本了解了各种方式的基本概念,下面举个列子详细讲解下。
新建一个场景,在此名字为test,加一个平行光,然后依次创建cube、Capsule、Sphere 三个对象,接着继续创建3个材质球( Material ),
分别为cube Material、 Capsule Material 、Sphere Material并给3种不同颜色:红、黄、蓝 。建好如下图
![](http://www.unitymanual.com/data/attachment/forum/201410/13/145610ifkiknyqnlikqntz.jpg.thumb.jpg)
1.创建代码TriggerTest ,如下
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
using
UnityEngine;
using
System.Collections;
public
class
TriggerTest : MonoBehaviour {
void
OnTriggerEnter( Collider other )
{
Debug.Log(other.name+
"通过触发器信息检测碰撞进入"
);
}
void
OnTriggerExit( Collider other )
{
Debug.Log(other.name +
"通过触发器信息检测碰撞退出"
);
}
void
OnTriggerStay( Collider other )
{
Debug.Log(other.name +
"通过触发器信息检测碰撞停留"
);
}
}
|
代码写好后,绑定脚本到红色Cube上运行,手动在Scene拖动任意其他对象去跟Cube碰撞,尴尬的事情来了,居然没有任何反应
这是什么情况?嘿嘿,看来我们还得完善下unity中有关碰撞器方面的知识啊,以下来自圣典翻译文档(蛮牛不会认为我打广告吧,为学东西拼啦)
![](http://www.unitymanual.com/data/attachment/forum/201410/13/154237ozxlgqogvr5ukcbs.jpg.thumb.jpg)
Static Collider 静态碰撞器、 Rigidbody Collider 刚体碰撞器、 Kinematic Rigidbody Collider 运动学刚体碰撞器这三种为常用类型,
其中, 这三种碰撞器如果勾选了IsTrigger复选框,就变成了相应的触发器。
还有个 表里面包含了检测到碰撞信息所必要的碰撞组合,总结很到位
![](http://www.unitymanual.com/data/attachment/forum/201410/13/154749c80fy286z0pb8y3f.jpg.thumb.jpg)
从表中可以看出,两个碰撞器要想检测到碰撞信息,至少有一个是Rigidbody Collider。这个就是我们刚才失败的关键
原来还有一个东西我们忘记了,那就是 Rigidbody(钢体) ,ok,我们给红色的cube 加上钢体,去掉Use Gravity勾选,这里
我们不需要使用重力,运行,移动黄色胶囊去碰撞红色cube
![](http://www.unitymanual.com/data/attachment/forum/201410/13/155650id9ndtx3xt93ux3s.jpg.thumb.jpg)
ok,是我们想要的结果。
简要终结下: 两个GameObject发生碰撞,要想检测到触发信息,最少要有一个刚体碰撞器并且勾选了IsTrigger复选框,另一个最少要有一个碰撞器组件,此时检测碰撞的脚本必须附加在那个带有刚体的触发器上。
可是,后面自己又测试一番下来 发现一个很奇怪的问题,触发器一直是红色Cube
1.我把钢体绑定到其他物体上,运行结果,只有cube去撞其他物体才能触发,手动拖动其他物体不触发。
2.接着我把脚本放到其他物体上,运行结果同上。
3.然后我把脚本放到其他物体上,钢体放红色Cube上,运行结果,只有手动拖动其他物体去撞cube触发,拖动cube去撞其他物体不触发。
剩下的 通过碰撞信息检测碰撞大家自行研究,在此我就不过多叙述,基本跟上同理,只不过不勾选Is Trigger就可以了,代码方法都换成 OnCollision xxx 的就可以了,不要忘记里面参数也要换 Collision collisionInfo 。
最后大家可能会问,着2种都是碰撞检测 在什么情况下用哪个呢?
我只说 使用Collision碰撞信息检测碰撞 是属于物理碰撞,如何使用 就看大家使用时是否需要具有物理特性碰撞了,没有就用Trigger触发保险点。
这里是圣殿的翻译文档地址也给大家,方便查看 :http://game.ceeger.com/Components/class-MeshCollider.html
接下来就是Ray射线检测及关于 layerMask的使用 ,这块在我前面帖子有专门的讲解【 unity射线碰撞检测+LayerMask的使用 】大家可以看下。
其实,这里我最想说的是关于Physics.Raycast()的用法,以前其实我自己都没注意这块,今天无意间发现原来里面还有这么多方便使用的函数
其中,包括 通过范围来查找怪物 等等,下面奉上 Physics.xx 函数方法
1) static function Raycast (origin : Vector3 , direction : Vector3 , distance : float = Mathf.Infinity , layerMask : int = kDefaultRaycastLayers) : bool
在origin坐标上建立一个方向为direction,距离为distance的射线,可以与layerMask(层遮罩)之外的所有的collider碰撞;
返回true如果碰撞到任何物体,否则返回false。 distance默认为无限远,layerMast默认为kDefaultRaycastLayers
只与第一个接触到的物体产生碰撞。
static function Raycast (origin : Vector3 , direction : Vector3 , out hitInfo : RaycastHit , distance : float = Mathf.Infinity , layerMask : int = kDefaultRaycastLayers) : bool
多了一个out hitInfo: RaycastHit, 如果碰撞到物体,具体碰撞数据和被碰撞体都会被记录在RaycastHit上,包括碰撞位置,碰撞位置法线,被碰撞体的Transform节点等信息。其他一样。
脚本:
var explosionPosition: Vector3;
var hit: RaycastHit;
if(Physics.Raycast(transform.position,target.position,hit,100)){
explosionPosition=hit.point;
}
static function Raycast (ray : Ray , distance : float = Mathf.Infinity , layerMask : int = kDefaultRaycastLayers) : bool
static function Raycast (ray : Ray , out hitInfo : RaycastHit , distance : float = Mathf.Infinity , layerMask : int = kDefaultRaycastLayers) : bool
直接由一个射线ray来指示位置和方向。其他一样。
2) static function RaycastAll (ray : Ray , distance : float = Mathf.Infinity , layerMask : int = kDefaultRaycastLayers) : RaycastHit []
static function RaycastAll (origin : Vector3 , direction : Vector3 , distance : float = Mathf.Infinity , layermask : int = kDefaultRaycastLayers) : RaycastHit []
与所有在ray这条射线上的物体碰撞并返回所有被碰撞体,RaycastHit[]。 其他同RaycastAll一样。
3)static function Linecast ( start : Vector3 , end : Vector3 , layerMask : int = kDefaultRaycastLayers) : bool
static function Linecast ( start : Vector3 , end : Vector3 , out hitInfo : RaycastHit , layerMask : int = kDefaultRaycastLayers) : bool
从start到end画一条直线,其他与Raycast和RaycastAll类似。 这个通常可以用于检测AI是否能看到目标物体等功能。
4) static function OverlapSphere (position : Vector3 , radius : float , layerMask : int = kAllLayers) : Collider []---可用于检查范围内的怪物
检测在position位置的半径radius的球形范围内是否存在可碰撞体并返回所有检测到的collider
5) static function CheckSphere (position : Vector3 , radius : float , layerMask : int = kDefaultRaycastLayers) : bool
当任何物体碰到position位置的半径为radius的球形范围时返回true;
6) static function CheckCapsule ( start : Vector3 , end : Vector3 , radius : float , layermask : int = kDefaultRaycastLayers) : bool
当任何物体碰到定义的胶囊体范围时返回true;
7) static function IgnoreCollision (collider1 : Collider , collider2 : Collider , ignore : bool = true) : void
控制collider1和collider2 是否可以碰撞。 ignore=true 两者将不会计算是否碰撞, ignore=false 则计算两者是否有碰撞。
原文地址:http://www.cnblogs.com/tonge/p/3614414.html 是不是挺有用?那还不赶快动手尝试下?
![](http://www.unitymanual.com/static/image/smiley/default/20119000.gif)