形状投射(Shape Casting)是物理引擎中的高级查询功能,可以沿指定方向"投射"一个三维形状来检测阻挡。与 射线检测 使用无限细的线不同,形状投射使用具有体积的几何体进行检测,能够提供更精确和实用的阻挡信息。
Galacean 物理引擎提供三种形状投射功能:
形状投射在游戏开发中有广泛应用:
盒子投射沿指定方向投射一个立方体,检测与场景中碰撞器的交集。
为了提升易用性,boxCast
提供了多个重载版本:
// 基础检测 - 仅返回是否被阻挡
boxCast(center: Vector3, halfExtents: Vector3, direction: Vector3): boolean
// 获取命中信息
boxCast(center: Vector3, halfExtents: Vector3, direction: Vector3, outHitResult: HitResult): boolean
// 指定投射距离
boxCast(center: Vector3, halfExtents: Vector3, direction: Vector3, distance: number): boolean
// 指定距离并获取命中信息
boxCast(center: Vector3, halfExtents: Vector3, direction: Vector3, distance: number, outHitResult: HitResult): boolean
// 完整参数版本
boxCast(
center: Vector3,
halfExtents: Vector3,
direction: Vector3,
orientation: Quaternion,
distance: number,
layerMask: Layer,
outHitResult?: HitResult
): boolean
import { Vector3, HitResult, Layer, Quaternion } from "@galacean/engine";
// 获取物理场景
const physicsScene = scene.physics;
// 示例1: 基础阻挡检测
const center = new Vector3(0, 5, 0);
const halfExtents = new Vector3(1, 1, 1); // 盒子半尺寸
const direction = new Vector3(0, -1, 0); // 向下投射
if (physicsScene.boxCast(center, halfExtents, direction)) {
console.log("检测到阻挡!");
}
// 示例2: 获取详细命中信息
const hitResult = new HitResult();
if (physicsScene.boxCast(center, halfExtents, direction, hitResult)) {
console.log(`命中实体: ${hitResult.entity.name}`);
console.log(`命中距离: ${hitResult.distance}`);
console.log(`命中点: ${hitResult.point.toString()}`);
console.log(`命中法线: ${hitResult.normal.toString()}`);
}
// 示例3: 角色移动预检测
const playerSize = new Vector3(0.5, 1, 0.5);
const moveDirection = new Vector3(1, 0, 0);
const moveDistance = 2.0;
if (!physicsScene.boxCast(playerPosition, playerSize, moveDirection, moveDistance)) {
// 路径安全,可以移动
playerPosition.add(moveDirection.scale(moveDistance));
}
// 示例4: 使用完整参数进行精确检测
const orientation = new Quaternion(0, 0, 0, 1); // 无旋转
const layerMask = Layer.Everything; // 检测所有层
const maxDistance = 10.0;
const detailHit = new HitResult();
if (physicsScene.boxCast(
center,
halfExtents,
direction,
orientation,
maxDistance,
layerMask,
detailHit
)) {
console.log("精确检测成功");
}
球体投射沿指定方向投射一个球形,适用于需要球形检测区域的场景。
// 基础检测
sphereCast(center: Vector3, radius: number, direction: Vector3): boolean
// 获取命中信息
sphereCast(center: Vector3, radius: number, direction: Vector3, outHitResult: HitResult): boolean
// 指定投射距离
sphereCast(center: Vector3, radius: number, direction: Vector3, distance: number): boolean
// 指定距离并获取命中信息
sphereCast(center: Vector3, radius: number, direction: Vector3, distance: number, outHitResult: HitResult): boolean
// 完整参数版本
sphereCast(
center: Vector3,
radius: number,
direction: Vector3,
distance: number,
layerMask: Layer,
outHitResult?: HitResult
): boolean
// 示例1: 球形物体移动预测
const ballRadius = 0.5;
const ballPosition = new Vector3(-5, 2, 0);
const rollDirection = new Vector3(1, 0, 0);
const rollDistance = 8.0;
const rollHit = new HitResult();
if (physicsScene.sphereCast(ballPosition, ballRadius, rollDirection, rollDistance, rollHit)) {
console.log(`球会在距离 ${rollHit.distance} 处撞到 ${rollHit.entity.name}`);
}
胶囊投射沿指定方向投射一个胶囊形状,特别适合人形角色的路径检测。
// 基础检测
capsuleCast(center: Vector3, radius: number, height: number, direction: Vector3): boolean
// 获取命中信息
capsuleCast(center: Vector3, radius: number, height: number, direction: Vector3, outHitResult: HitResult): boolean
// 指定投射距离
capsuleCast(center: Vector3, radius: number, height: number, direction: Vector3, distance: number): boolean
// 指定距离并获取命中信息
capsuleCast(center: Vector3, radius: number, height: number, direction: Vector3, distance: number, outHitResult: HitResult): boolean
// 完整参数版本
capsuleCast(
center: Vector3,
radius: number,
height: number,
direction: Vector3,
orientation: Quaternion,
distance: number,
layerMask: Layer,
outHitResult?: HitResult
): boolean
// 示例1: 角色跳跃检测
const characterCenter = new Vector3(0, 1, 0);
const characterRadius = 0.5;
const characterHeight = 1.8;
const jumpDirection = new Vector3(0, 1, 0);
const jumpHeight = 2.0;
if (!physicsScene.capsuleCast(characterCenter, characterRadius, characterHeight, jumpDirection, jumpHeight)) {
// 头顶空间足够,可以跳跃
performJump();
}
// 示例2: 人形角色移动检测
const moveDirection = new Vector3(1, 0, 0);
const stepDistance = 1.0;
const moveHit = new HitResult();
if (physicsScene.capsuleCast(
characterCenter,
characterRadius,
characterHeight,
moveDirection,
stepDistance,
moveHit
)) {
console.log(`角色移动会在 ${moveHit.distance} 处碰到障碍物`);
// 可以实现滑动或其他阻挡响应
}
Number.MAX_VALUE
)Layer.Everything
)layerMask
只检测相关的碰撞器层// 性能优化示例
class PhysicsQuery {
private static readonly _hitResult = new HitResult();
private static readonly _playerLayerMask = Layer.Layer0 | Layer.Layer1;
static checkPlayerMovement(center: Vector3, direction: Vector3): boolean {
return scene.physics.capsuleCast(
center,
0.5, // 固定半径
1.8, // 固定高度
direction,
2.0, // 限制检测距离
this._playerLayerMask, // 只检测相关层
this._hitResult // 重用结果对象
);
}
}
direction
参数是单位向量特性 | 射线检测 | 形状投射 |
---|---|---|
检测精度 | 点精度 | 体积精度 |
性能消耗 | 低 | 中等 |
适用场景 | 点选、瞄准 | 移动预测、路径验证 |
形状投射提供了比射线检测更精确的阻挡信息,特别适合需要考虑物体体积的应用场景。结合合适的性能优化策略,可以在保证精度的同时维持良好的运行效率。