勇哥注:
碰撞检测和触发器都可以用于检测轴运动是不是撞机了。
如果我们的动作逻辑有撞机的可能性,就可以用它来检测到。
对于含有相机的设备,则可以使用射线检测取得物料的信息。
(一)基本的碰撞检测组件介绍
碰撞组件名字没带2D的,都是3D的碰撞组件。
Box Collider, Sphere Collider是盒子与球体的碰撞组件。
其它几种是非简单几何体的复杂碰撞检测:
Mesh Collider
网格碰撞体,它能精确匹配例如树木、建筑、岩石、任意形状的模型。
因为三角网格具有大量顶点,这种碰撞检测就比较耗性能。
它有一个Convex选项,可以把网格简化为凸包,减少碰撞检测的复杂度。
显然,如果我们要做轴碰撞的检测时,轴带动的机械部件可能就属于一种任意形状,就适合使用此碰撞器。
Terrain Collider
这个是专门与Terrain(地形)对象配合的。用于实现物体与地形的物理交互。
Wheel Collider
专门为车辆设计的碰撞组件。
它不仅仅是一个普通的碰撞体,还能够模拟悬挂、轮胎摩擦和车轮转动等物理效果。
包含了对悬挂、转向、牵引力、制动力等的计算。
基于Raycast(射线检测)来计算车轮与地面之间的物理交互,而不是通过几何形状检测碰撞。
(二)碰撞检测的参数
我们以Box Collider为例。
box collider是一个立方体的检测框,默认跟这个Cube物体一样大小。
你可以通过“中心”、“大小”来调节检测框的大小。
碰撞检测就是以这个检测框来进行计算。
这个Cube如果添加了RigidBody刚体组件,它落到其它物体上时,就是用检测框碰撞,你会观察到Cube会浮在了地面上。
如果勾选“是触发器”,则此物体不再会影响碰撞,也就是其它物体可以穿过它。
而是可以触发另一种事件。详细见后面第四节的解释。
(三)代码监听碰撞事件
//监听发生碰撞
private void OnCollisionEnter(Collision collision)
{
//这里的参数collision,含有火焰和地面碰撞的信息。
//创建一个爆炸物体
Instantiate(Prefab,transform.position, Quaternion.identity);
//销毁自身
Destroy(gameObject);
//获取碰撞到的物体
Debug.Log(collision.gameObject.name);
}
//持续碰撞中
private void OnCollisionStay(Collision collision)
{
}
//结束碰撞
private void OnCollisionExit(Collision collision)
{
}
(四)触发器事件
触发器是十分有用的功能,我们在自动化设备中用它来模拟物理感应器。
轴的原点、限位;气缸的动点、原点磁性感应器;物料感应器、光纤等等,都可以用触发器来模拟。
应用触发器时,对象本体一般需要隐藏,可以去掉下图中这个勾。它就不会在视图中进行渲染显示了。
但是物体还是存在的。
//监听触发
private void OnTriggerEnter(Collider other)
{
GameObject door=GameObject.Find("Door");
if(door!=null)
{
door.SetActive(false); //门消失
}
}
//持续触发
private void OnTriggerStay(Collider other)
{
}
//结束触发
private void OnTriggerExit(Collider other)
{
}
(五)射线检测
射线检测是从摄像机的近平面,发出一根射线,如果这跟线碰到了对象,则报靠碰撞信息(如位置信息)。
这东西有什么用呢?
首先,Unity中的UI组件,其实是基于射线检测来判断用户点击的。
然后就是玩家的瞄准和射击,射线检测可用于判断玩家的视线或射击方向与敌人或其他目标是否相交,从而确定是否击中目标
还可以碰撞避免,AI角色在移动时,可以使用射线检测来检测前方的障碍物,从而避免碰撞。
总结:它是从摄像机,你的眼睛出发,向前发出射线,来检测前方是否有障碍物。
这种跟用碰撞组件检测物体碰撞的机制完全不同。更像是模拟人在行走时用眼睛看路的效果。
在自动化设备中,如果你的相机眼在手上的(即相机会移动,可能是随着模组移动,或者随着机器人的某个关节移动),
则射线检测可以得到相机距离物料的高度、位置信息、以及可以检测到与物料是否碰撞。
如果使用碰撞组件,则需要给物料和相机同时添加碰撞组件。
身线检测的一个例子,鼠标点击到哪里,对象就移动到哪里
有人可能提问,鼠标点击后不是有坐标信息吗,为啥还要用射线检测取得位置信息?
因为鼠标点击的坐标,是屏幕坐标(二维信息),不是场景的3D空间的坐标(三维信息)。
void Start()
{
//方式1
// Ray ray=new Ray(Vector3.zero, Vector3.up);
//方式2
// Ray ray=Camera.main.ScreenPointToRay(Input.mousePosition);
}
//如果鼠标左键点击,则对象移动到点击的位置
void Update()
{
if(Input.GetMouseButtonDown(0))
{
//按下鼠标左键发射射线
Ray ray=Camera.main.ScreenPointToRay(Input.mousePosition);
//声明一个碰撞信息类
RaycastHit hit;
//碰撞检测
bool res=Physics.Rasycast(ray,out hit);
//如果碰撞到了,hit就有内容
if(res==true)
{
Debug.Log(hit.point);
transform.position=hit.point;
}
//多检测, 最后一参数是过滤掉某些图层的对象,不要理会
RaycastHit[] hits=Physics.RaycastAll(ray, 100, 1<<10);
}
}

