unity不使用刚体的碰撞检测

2015年10月12日 11:37 1 点赞 0 评论 更新于 2025-11-21 19:10

一、文章目的

本文旨在让读者了解在Unity中如何进行不使用刚体的碰撞检测。虽然通常在Unity里检查的只是垂直运动方向,但可以通过修改脚本,向场景中添加对象来检查其他方向,或者更改立方体的位置。

二、Unity与刚体概述

Unity是一款强大的3D游戏引擎,内置了Nvidia PhysX物理引擎。在Unity中,若要对游戏对象应用物理模拟,该对象必须具有刚体组件,刚体也常用于碰撞检测。

不过,假设我们仅需要碰撞检测,而不进行物理模拟,此时单纯为了碰撞检测使用物理引擎可能会降低整体性能。

三、解决方案

方案一:使刚体运动学化并捕获触发器事件

方案二:不使用刚体(可能是最佳方案)

使用Raycast(射线投射)是一个不错的选择。即便每帧投射数以百计的光线,其性能损耗也相对较小。Raycast提供了一种从指定源点沿特定方向投射射线,并判断该射线是否与任何碰撞器相交的方法。我们可以通过在x轴和y轴上投射射线,来确认游戏物体的周围环境,进而处理碰撞检测。

具体步骤如下:

  1. 获取游戏对象的方向
  2. 投射光线
  3. 根据命中结果确定碰撞体

简单的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相撞时返回。

步骤

  1. 创建3个Cube:在场景中创建3个Cube,具体布局可参考后续说明。
  2. 添加Box Collider:为所有Cube添加Box Collider组件。
  3. 添加脚本:将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;
}
}

代码解释

  • NoOfRaysMovingForce是公共变量,可在运行时根据需要进行调整。需要注意的是,要确保移动速度不超过Cube在顶部和底部之间的距离。
  • DirectionFactor用于成倍增加运动力和射线的方向,以此决定Cube的运动方向。最初,它被设置为向上(正y轴)方向。当Cube与其他Cube相撞时,该方向会被反转。通过改变方向矢量,我们可以根据需求改变Cube的运动方向。DirectionFactor仅用于反转方向。

五、来源与作者

作者信息

洞悉

洞悉

共发布了 3994 篇文章