Files
engine/docs/zh/physics/collider/dynamicCollider.mdx
luzhuang f6b696583e Doc: opt physics doc (#2551)
* feat: opt physics doc
2025-03-07 16:41:40 +08:00

294 lines
12 KiB
Plaintext

---
order: 2
title: 动态碰撞器
type: 物理
label: Physics
---
动态碰撞器([DynamicCollider](/apis/core/#DynamicCollider))用于模拟可以自由运动并受物理影响的物体。它可以响应重力、受力、碰撞等物理作用,适用于需要真实物理模拟的游戏物体。
## 使用方法
1. 选中目标实体,并在检查器中点击添加组件按钮,添加 DynamicCollider 组件。
<Image src="https://mdn.alipayobjects.com/huamei_3zduhr/afts/img/A*Ep4xTqWpligAAAAAAAAAAAAAesJ_AQ/original" />
2. 为碰撞器添加碰撞形状。动态碰撞器支持添加多个碰撞形状,关于碰撞形状的详细说明请参考[碰撞形状](/docs/physics/collider/colliderShape)文档。目前支持以下类型:
<Image src="https://mdn.alipayobjects.com/huamei_3zduhr/afts/img/A*np90QZkKqXUAAAAAAAAAAAAAesJ_AQ/original" />
3. 调整碰撞形状的位置、大小等属性,使其与场景元素匹配。
<Image src="https://mdn.alipayobjects.com/huamei_3zduhr/afts/img/A*QthGTLWFSh8AAAAAAAAAAAAAesJ_AQ/original" />
4. 根据需要设置碰撞器的属性调整物体的物理行为,各属性的含义和作用请参考下文。
## 属性说明
### 继承自 Collider 的属性
| 属性 | 描述 |
| ----------------------------------------- | ------------ |
| [**shapes**](/apis/core/#Collider-shapes) | 碰撞形状集合 |
### 特有属性
| 属性 | 描述 | 默认值 |
| --------------- | --------------------------------------------------------- | ------ |
| [**mass**](/apis/core/#DynamicCollider-mass) | 碰撞器的质量,质量越大物体运动状态越难改变 | 1.0 |
| [**useGravity**](/apis/core/#DynamicCollider-useGravity) | 是否受重力影响 | true |
| [**isKinematic**](/apis/core/#DynamicCollider-isKinematic) | 是否为运动学物体,运动学物体不受物理影响但可以影响其他物体 | false |
### 速度设置
| 属性 | 描述 | 默认值 |
| ---------------------------- | ------------------------------------------- | ------- |
| [**linearVelocity**](/apis/core/#DynamicCollider-linearVelocity) | 线性速度向量(世界单位/秒) | (0,0,0) |
| [**angularVelocity**](/apis/core/#DynamicCollider-angularVelocity) | 角速度向量(度/秒) | (0,0,0) |
| [**maxAngularVelocity**](/apis/core/#DynamicCollider-maxAngularVelocity) | 最大角速度限制(度/秒) | 18000/π |
| [**maxDepenetrationVelocity**](/apis/core/#DynamicCollider-maxDepenetrationVelocity) | 碰撞体重叠时的最大分离速度,用于防止物体穿透 | 1e32 |
### 阻尼
| 属性 | 描述 | 默认值 |
| ------------------ | ---------------- | ------ |
| [**linearDamping**](/apis/core/#DynamicCollider-linearDamping) | 线性运动阻尼系数 | 0 |
| [**angularDamping**](/apis/core/#DynamicCollider-angularDamping) | 角速度阻尼系数 | 0.05 |
### 质量/惯性张量
| 属性 | 描述 | 默认值 |
| -------------------------- | ------------------------ | ------- |
| [**centerOfMass**](/apis/core/#DynamicCollider-centerOfMass) | 质心相对于变换原点的位置 | (0,0,0) |
| [**automaticCenterOfMass**](/apis/core/#DynamicCollider-automaticCenterOfMass) | 是否自动计算质心位置 | true |
| [**inertiaTensor**](/apis/core/#DynamicCollider-inertiaTensor) | 物体相对于质心的惯性张量 | (1,1,1) |
| [**automaticInertiaTensor**](/apis/core/#DynamicCollider-automaticInertiaTensor) | 是否自动计算惯性张量 | true |
### 性能优化设置
| 属性 | 描述 | 默认值 |
| -------------------- | --------------------------------------- | ------ |
| [**sleepThreshold**](/apis/core/#DynamicCollider-sleepThreshold) | 休眠阈值,物体运动能量低于此值时进入休眠 | 0.005 |
| [**solverIterations**](/apis/core/#DynamicCollider-solverIterations) | 约束求解迭代次数 | 4 |
<Callout type="info">
约束求解是物理引擎用来解决物体之间碰撞和约束的计算过程。每次迭代都会尝试调整物体的位置和速度,使其满足所有的物理约束(如碰撞、关节等)。
- 迭代次数越多,物理表现越准确,但计算开销也越大
- 迭代次数过少可能导致物体出现抖动或穿透
- 建议根据实际需求平衡精度和性能:
- 一般物体:使用默认值 4
- 精确物理:可以增加到 6-8
- 性能优先:可以降低到 2-3
</Callout>
### 运动约束
- [**constraints**](/apis/core/#DynamicCollider-constraints)
用于限制物体在特定轴向上的运动。可以分别锁定位置和旋转的X、Y、Z轴向运动。
```typescript
// 限制Y轴位置和所有旋转
collider.constraints =
DynamicColliderConstraints.FreezePositionY |
DynamicColliderConstraints.FreezeRotationX |
DynamicColliderConstraints.FreezeRotationY |
DynamicColliderConstraints.FreezeRotationZ;
```
### 碰撞检测模式
- [**collisionDetectionMode**](/apis/core/#DynamicCollider-collisionDetectionMode)
用于控制物体碰撞检测的精确程度:
| 模式 | 描述 | 适用场景 | 性能消耗 |
| ---- | ---- | -------- | -------- |
| **Discrete** | 最基础的检测模式,按固定的时间步长检测碰撞,可能在高速运动时发生穿透 | 低速物体 | 最低 |
| **Continuous** | 对静态碰撞体使用连续碰撞检测,可以防止高速物体穿透静态物体 | 高速投射物 | 中等 |
| **ContinuousDynamic** | 对所有碰撞体使用连续碰撞检测,可以防止高速物体之间的相互穿透 | 精确物理模拟 | 较高 |
| **ContinuousSpeculative** | 使用推测算法进行连续碰撞检测,性能消耗介于 Discrete 和 Continuous 之间 | 一般游戏场景 | 中等 |
#### 设置碰撞检测模式示例
```typescript
// 1. 普通物体使用离散检测
normalObject.collisionDetectionMode = CollisionDetectionMode.Discrete;
// 2. 投射物使用连续检测防止穿墙
projectile.collisionDetectionMode = CollisionDetectionMode.Continuous;
// 3. 重要物理交互使用完全连续检测
importantPhysicsObject.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
// 4. 一般游戏物体使用推测性检测
gameObject.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative;
```
#### 选择建议
1. **基于物体速度选择**
- 低速物体:使用 Discrete
- 中速物体:使用 ContinuousSpeculative
- 高速物体:使用 Continuous 或 ContinuousDynamic
2. **基于重要性选择**
- 普通场景物体:使用 Discrete
- 游戏关键物体:使用 ContinuousSpeculative
- 必须精确的物理交互:使用 ContinuousDynamic
3. **基于性能选择**
- 性能优先:使用 Discrete
- 性能与精度平衡:使用 ContinuousSpeculative
- 精度优先:使用 ContinuousDynamic
## 公开方法
### 继承自 Collider 的方法
| 方法名 | 描述 |
| --------------------------------------------------- | ---------------- |
| [**addShape**](/apis/core/#Collider-addShape) | 添加碰撞形状 |
| [**removeShape**](/apis/core/#Collider-removeShape) | 移除指定碰撞形状 |
| [**clearShapes**](/apis/core/#Collider-clearShapes) | 清空所有碰撞形状 |
### 特有方法
| 方法名 | 描述 |
| --------------- | ------------------ |
| [**applyForce**](/apis/core/#DynamicCollider-applyForce) | 施加力 |
| [**applyTorque**](/apis/core/#DynamicCollider-applyTorque) | 施加扭矩 |
| [**move**](/apis/core/#DynamicCollider-move) | 运动学移动 |
| [**sleep**](/apis/core/#DynamicCollider-sleep) | 强制休眠 |
| [**wakeUp**](/apis/core/#DynamicCollider-wakeUp) | 唤醒物体 |
| [**isSleeping**](/apis/core/#DynamicCollider-isSleeping) | 检查是否在休眠状态 |
## 脚本使用
### 基础配置
```typescript
// 创建动态碰撞器
const dynamicCollider = entity.addComponent(DynamicCollider);
// 添加碰撞形状
const boxShape = new BoxColliderShape();
boxShape.size = new Vector3(1, 1, 1);
dynamicCollider.addShape(boxShape);
// 配置基本物理属性
dynamicCollider.mass = 1.0; // 设置质量
dynamicCollider.useGravity = true; // 启用重力
dynamicCollider.isKinematic = false; // 设置为动力学模式
```
### 运动控制
```typescript
class PhysicsController extends Script {
private _collider: DynamicCollider;
onAwake() {
// 获取动态碰撞器引用
this._collider = this.entity.getComponent(DynamicCollider);
// 配置运动阻尼
this._collider.linearDamping = 0.1; // 设置线性阻尼
this._collider.angularDamping = 0.1; // 设置角速度阻尼
// 设置运动约束
this._collider.constraints =
DynamicColliderConstraints.FreezeRotationX | // 锁定X轴旋转
DynamicColliderConstraints.FreezeRotationZ; // 锁定Z轴旋转
}
onUpdate() {
// 获取当前速度
const velocity = this._collider.linearVelocity;
// 设置速度
this._collider.linearVelocity = new Vector3(5, velocity.y, 0);
// 施加持续力(如推力)
if (this.engine.inputManager.isKeyHeldDown(Keys.W)) {
this._collider.applyForce(new Vector3(0, 0, 10));
}
// 施加瞬时力(如跳跃)
if (this.engine.inputManager.isKeyDown(Keys.Space)) {
this._collider.applyForce(new Vector3(0, 500, 0));
}
// 施加扭矩(使物体旋转)
if (this.engine.inputManager.isKeyHeldDown(Keys.R)) {
this._collider.applyTorque(new Vector3(0, 10, 0));
}
}
}
```
### 运动学控制
```typescript
class KinematicController extends Script {
private _collider: DynamicCollider;
onAwake() {
this._collider = this.entity.getComponent(DynamicCollider);
this._collider.isKinematic = true; // 设置为运动学模式
}
// 实现电梯运动
onUpdate() {
const time = this.engine.time.elapsedTime;
const position = new Vector3(0, Math.sin(time) * 2, 0);
this._collider.move(position);
}
}
```
### 休眠管理
```typescript
class SleepController extends Script {
private _collider: DynamicCollider;
onAwake() {
this._collider = this.entity.getComponent(DynamicCollider);
// 配置休眠参数
this._collider.sleepThreshold = 0.005; // 设置休眠阈值
}
onUpdate() {
// 检查是否处于休眠状态
if (this._collider.isSleeping()) {
console.log("物体已休眠");
}
// 手动控制休眠
if (this.engine.inputManager.isKeyDown(Keys.S)) {
this._collider.sleep(); // 强制休眠
}
if (this.engine.inputManager.isKeyDown(Keys.W)) {
this._collider.wakeUp(); // 唤醒物体
}
}
}
```
### 质量/惯性张量设置
```typescript
// 自动计算
const collider = entity.addComponent(DynamicCollider);
collider.mass = 1.0;
collider.automaticCenterOfMass = true; // 自动计算质心
collider.automaticInertiaTensor = true; // 自动计算惯性张量
// 手动设置
const customCollider = entity.addComponent(DynamicCollider);
customCollider.automaticCenterOfMass = false;
customCollider.automaticInertiaTensor = false;
customCollider.centerOfMass = new Vector3(0, 0.5, 0); // 手动设置质心
customCollider.inertiaTensor = new Vector3(1, 1, 1); // 手动设置惯性张量
```