unity不使用刚体的碰撞检测
一、文章目的
本文旨在让读者了解在Unity中如何进行不使用刚体的碰撞检测。虽然通常在Unity里检查的只是垂直运动方向,但可以通过修改脚本,向场景中添加对象来检查其他方向,或者更改立方体的位置。
二、Unity与刚体概述
Unity是一款强大的3D游戏引擎,内置了Nvidia PhysX物理引擎。在Unity中,若要对游戏对象应用物理模拟,该对象必须具有刚体组件,刚体也常用于碰撞检测。
不过,假设我们仅需要碰撞检测,而不进行物理模拟,此时单纯为了碰撞检测使用物理引擎可能会降低整体性能。
三、解决方案
方案一:使刚体运动学化并捕获触发器事件
方案二:不使用刚体(可能是最佳方案)
使用Raycast(射线投射)是一个不错的选择。即便每帧投射数以百计的光线,其性能损耗也相对较小。Raycast提供了一种从指定源点沿特定方向投射射线,并判断该射线是否与任何碰撞器相交的方法。我们可以通过在x轴和y轴上投射射线,来确认游戏物体的周围环境,进而处理碰撞检测。
具体步骤如下:
- 获取游戏对象的方向
- 投射光线
- 根据命中结果确定碰撞体
简单的Raycast代码示例如下:
if (Physics.Raycast(transform.position, Vector3.forward, 10))
print("There is something in front of the object!");
在上述代码中,第一个参数是射线的原点,第二个参数是射线的方向,第三个参数是射线的长度。Unity还允许我们获取射线投射的结果,示例如下:
RaycastHit hitInfo;
if (Physics.Raycast(transform.position, Vector3.down, out hitInfo))
print("There is something " + hitInfo.distance + "m away from gameobject");
四、实例演示
接下来,我们通过一个实例来展示如何实现不使用刚体的碰撞检测。假设我们要让一个Cube在与另一个Cube相撞时返回。
步骤
- 创建3个Cube:在场景中创建3个Cube,具体布局可参考后续说明。
- 添加Box Collider:为所有Cube添加Box Collider组件。
- 添加脚本:将CollisionDetector脚本添加到中间的Cube上,该Cube位于其他两个Cube之间。在CollisionDetector脚本中,实现当中间的Cube与上方或下方的Cube碰撞时,改变其运动方向。
代码实现
using UnityEngine;
using System.Collections;
public class CollisionDetector : MonoBehaviour
{
public float MovingForce;
Vector3 StartPoint;
Vector3 Origin;
public int NoOfRays = 10;
int i;
RaycastHit HitInfo;
float LengthOfRay, DistanceBetweenRays, DirectionFactor;
float margin = 0.015f;
Ray ray;
void Start ()
{
// Length of the Ray is distance from center to edge
LengthOfRay = collider.bounds.extents.y;
// Initialize DirectionFactor for upward direction
DirectionFactor = Mathf.Sign (Vector3.up.y);
}
void Update ()
{
// First ray origin point for this frame
StartPoint = new Vector3 (collider.bounds.min.x + margin, transform.position.y, transform.position.z);
if (!IsCollidingVertically ())
{
transform.Translate (Vector3.up * MovingForce * Time.deltaTime * DirectionFactor);
}
}
bool IsCollidingVertically ()
{
Origin = StartPoint;
DistanceBetweenRays = (collider.bounds.size.x - 2 * margin) / (NoOfRays - 1);
for (i = 0; i < NoOfRays; i++)
{
// Ray to be casted.
ray = new Ray (Origin, Vector3.up * DirectionFactor);
// Draw ray on screen to see visually. Remember visual length is not actual length.
Debug.DrawRay (Origin, Vector3.up * DirectionFactor, Color.yellow);
if (Physics.Raycast (ray, out HitInfo, LengthOfRay))
{
print ("Collided With " + HitInfo.collider.gameObject.name);
// Negate the Directionfactor to reverse the moving direction of colliding cube(here cube2)
DirectionFactor = -DirectionFactor;
return true;
}
Origin += new Vector3 (DistanceBetweenRays, 0, 0);
}
return false;
}
}
代码解释
NoOfRays和MovingForce是公共变量,可在运行时根据需要进行调整。需要注意的是,要确保移动速度不超过Cube在顶部和底部之间的距离。DirectionFactor用于成倍增加运动力和射线的方向,以此决定Cube的运动方向。最初,它被设置为向上(正y轴)方向。当Cube与其他Cube相撞时,该方向会被反转。通过改变方向矢量,我们可以根据需求改变Cube的运动方向。DirectionFactor仅用于反转方向。