mirror of
https://github.com/galacean/engine.git
synced 2026-05-31 07:42:01 +08:00
293 lines
9.8 KiB
Plaintext
293 lines
9.8 KiB
Plaintext
---
|
||
order: 4
|
||
title: 碰撞形状
|
||
type: 物理
|
||
label: Physics
|
||
---
|
||
|
||
碰撞形状([ColliderShape](/apis/core/#ColliderShape))定义了碰撞器的物理外形。Galacean 提供了多种基础碰撞形状,可以通过组合这些形状来构建复杂的碰撞区域。
|
||
|
||
## 支持的形状类型
|
||
|
||
<Image src="https://mdn.alipayobjects.com/huamei_3zduhr/afts/img/A*jsEBTIs9C_MAAAAAAAAAAAAAesJ_AQ/original" />
|
||
|
||
| 形状类型 | 特点 | 后端支持 |
|
||
| -------- | ---- | -------- |
|
||
| [**BoxColliderShape**](/apis/core/#BoxColliderShape) | 最基础的碰撞形状<br/>适用于方形、矩形物体<br/>可以通过 size 属性调整三个轴向的大小 | 所有物理后端 |
|
||
| [**SphereColliderShape**](/apis/core/#SphereColliderShape) | 用于球形物体的碰撞检测<br/>通过 radius 属性设置半径 | 所有物理后端 |
|
||
| [**PlaneColliderShape**](/apis/core/#PlaneColliderShape) | 无限大的平面碰撞体<br/>通常用作地面 | 仅 physics-physx 后端 |
|
||
| [**CapsuleColliderShape**](/apis/core/#CapsuleColliderShape) | 由圆柱体和两个半球组成<br/>适用于角色碰撞器<br/>可以设置 radius 和 height | 仅 physics-physx 后端 |
|
||
|
||
## 基本属性
|
||
|
||
### 变换属性
|
||
- [**position**](/apis/core/#ColliderShape-position)
|
||
形状相对于碰撞器实体的局部位置偏移。
|
||
|
||
- [**rotation**](/apis/core/#ColliderShape-rotation)
|
||
形状相对于碰撞器实体的局部旋转。
|
||
|
||
### 物理材质
|
||
- [**material**](/apis/core/#ColliderShape-material)
|
||
定义形状的物理材质属性。每个碰撞形状都需要有一个物理材质,用于定义其物理特性:
|
||
|
||
| 属性 | 描述 | 默认值 |
|
||
| ---- | ---- | ------ |
|
||
| [**staticFriction**](/apis/core/#PhysicsMaterial-staticFriction) | 物体静止时的摩擦系数,值越大物体越难开始移动 | 0.6 |
|
||
| [**dynamicFriction**](/apis/core/#PhysicsMaterial-dynamicFriction) | 物体运动时的摩擦系数,值越大物体移动时受到的阻力越大 | 0.6 |
|
||
| [**bounciness**](/apis/core/#PhysicsMaterial-bounciness) | 碰撞反弹程度,取值范围 0-1,0 表示完全不反弹,1 表示完全弹性碰撞 | 0 |
|
||
| [**bounceCombine**](/apis/core/#PhysicsMaterial-bounceCombine) | 定义两个碰撞物体的弹性系数如何组合: <ul><li>Average: 取两者平均值(默认)</li><li>Minimum: 取两者中的最小值</li><li>Maximum: 取两者中的最大值</li><li>Multiply: 将两者相乘</li></ul> | Average |
|
||
| [**frictionCombine**](/apis/core/#PhysicsMaterial-frictionCombine) | 定义两个碰撞物体的摩擦系数如何组合: <ul><li>Average: 取两者平均值(默认)</li><li>Minimum: 取两者中的最小值</li><li>Maximum: 取两者中的最大值</li><li>Multiply: 将两者相乘</li></ul> | Average |
|
||
|
||
### 触发器设置
|
||
- [**isTrigger**](/apis/core/#ColliderShape-isTrigger)
|
||
是否作为触发器使用:
|
||
- true:只触发触发器事件,不产生物理反应
|
||
- false:正常的物理碰撞(默认)
|
||
|
||
|
||
有关碰撞和触发器事件的详细信息,请参阅[碰撞事件](/docs/physics/collider/event)文档。
|
||
|
||
## 脚本使用
|
||
|
||
### 创建基础形状
|
||
|
||
```typescript
|
||
// 创建盒形碰撞器
|
||
const boxShape = new BoxColliderShape();
|
||
boxShape.size = new Vector3(1, 1, 1);
|
||
boxShape.position = new Vector3(0, 0.5, 0);
|
||
|
||
// 创建球形碰撞器
|
||
const sphereShape = new SphereColliderShape();
|
||
sphereShape.radius = 0.5;
|
||
sphereShape.position = new Vector3(0, 1, 0);
|
||
|
||
// 创建胶囊体碰撞器
|
||
const capsuleShape = new CapsuleColliderShape();
|
||
capsuleShape.radius = 0.5;
|
||
capsuleShape.height = 2;
|
||
|
||
// 创建平面碰撞器
|
||
const planeShape = new PlaneColliderShape();
|
||
```
|
||
|
||
|
||
|
||
### 形状管理
|
||
|
||
```typescript
|
||
// 获取所有形状
|
||
const shapes = staticCollider.shapes;
|
||
|
||
// 增加形状
|
||
const boxShape = new BoxColliderShape();
|
||
staticCollider.addShape(boxShape);
|
||
|
||
// 移除特定形状
|
||
staticCollider.removeShape(boxShape);
|
||
|
||
// 清空所有形状
|
||
staticCollider.clearShapes();
|
||
```
|
||
|
||
|
||
### 设置物理材质
|
||
|
||
```typescript
|
||
// 创建物理材质并配置属性
|
||
const material = new PhysicsMaterial();
|
||
material.staticFriction = 0.6; // 静摩擦系数
|
||
material.dynamicFriction = 0.4; // 动摩擦系数
|
||
material.bounciness = 0.5; // 弹性系数
|
||
|
||
// 设置材质的组合模式
|
||
material.frictionCombine = PhysicsMaterialCombineMode.Average; // 摩擦力组合方式
|
||
material.bounceCombine = PhysicsMaterialCombineMode.Maximum; // 弹性组合方式
|
||
|
||
// 将材质应用到碰撞形状
|
||
const shape = new BoxColliderShape();
|
||
shape.material = material;
|
||
|
||
// 为不同的形状设置不同的材质
|
||
const iceShape = new BoxColliderShape();
|
||
const iceMaterial = new PhysicsMaterial();
|
||
iceMaterial.staticFriction = 0.1;
|
||
iceMaterial.dynamicFriction = 0.05;
|
||
iceMaterial.bounciness = 0;
|
||
iceShape.material = iceMaterial;
|
||
|
||
const bounceShape = new SphereColliderShape();
|
||
const bounceMaterial = new PhysicsMaterial();
|
||
bounceMaterial.bounciness = 0.8;
|
||
bounceMaterial.bounceCombine = PhysicsMaterialCombineMode.Maximum;
|
||
bounceShape.material = bounceMaterial;
|
||
|
||
// 不再使用时记得销毁材质
|
||
material.destroy();
|
||
iceMaterial.destroy();
|
||
bounceMaterial.destroy();
|
||
```
|
||
|
||
### 创建复合形状
|
||
|
||
```typescript
|
||
// 创建带有多个碰撞形状的物体
|
||
function createCompoundCollider(entity: Entity) {
|
||
const collider = entity.addComponent(DynamicCollider);
|
||
|
||
// 主体形状
|
||
const mainShape = new BoxColliderShape();
|
||
mainShape.size = new Vector3(2, 1, 1);
|
||
collider.addShape(mainShape);
|
||
|
||
// 顶部形状
|
||
const topShape = new BoxColliderShape();
|
||
topShape.size = new Vector3(1, 1, 1);
|
||
topShape.position = new Vector3(0, 1, 0);
|
||
collider.addShape(topShape);
|
||
|
||
return collider;
|
||
}
|
||
```
|
||
|
||
### 常用场景示例
|
||
|
||
1. **创建地面**
|
||
```typescript
|
||
// 创建一个简单的地面
|
||
function createGround(width: number, length: number): Entity {
|
||
const entity = new Entity();
|
||
const collider = entity.addComponent(StaticCollider);
|
||
|
||
const groundShape = new BoxColliderShape();
|
||
groundShape.size = new Vector3(width, 0.1, length);
|
||
|
||
// 设置地面的物理材质
|
||
const material = new PhysicsMaterial();
|
||
material.staticFriction = 0.6;
|
||
material.dynamicFriction = 0.6;
|
||
material.bounciness = 0.0;
|
||
groundShape.material = material;
|
||
|
||
collider.addShape(groundShape);
|
||
return entity;
|
||
}
|
||
|
||
// 创建一个无限平面地面
|
||
function createInfinitePlane(): Entity {
|
||
const entity = new Entity();
|
||
const collider = entity.addComponent(StaticCollider);
|
||
|
||
const planeShape = new PlaneColliderShape();
|
||
// 设置地面材质
|
||
const material = new PhysicsMaterial();
|
||
material.staticFriction = 0.6;
|
||
material.dynamicFriction = 0.6;
|
||
planeShape.material = material;
|
||
|
||
collider.addShape(planeShape);
|
||
return entity;
|
||
}
|
||
```
|
||
|
||
2. **创建墙壁**
|
||
```typescript
|
||
// 创建一个可配置的墙壁
|
||
function createWall(width: number, height: number, depth: number, friction: number = 0.6): Entity {
|
||
const entity = new Entity();
|
||
const collider = entity.addComponent(StaticCollider);
|
||
|
||
const wallShape = new BoxColliderShape();
|
||
wallShape.size = new Vector3(width, height, depth);
|
||
|
||
// 设置墙壁的物理材质
|
||
const material = new PhysicsMaterial();
|
||
material.staticFriction = friction;
|
||
material.dynamicFriction = friction;
|
||
material.bounciness = 0.0;
|
||
wallShape.material = material;
|
||
|
||
collider.addShape(wallShape);
|
||
return entity;
|
||
}
|
||
```
|
||
|
||
3. **创建斜坡**
|
||
```typescript
|
||
// 创建一个带摩擦力的斜坡
|
||
function createSlope(width: number, height: number, angle: number): Entity {
|
||
const entity = new Entity();
|
||
const collider = entity.addComponent(StaticCollider);
|
||
|
||
const slopeShape = new BoxColliderShape();
|
||
slopeShape.size = new Vector3(width, 0.1, height);
|
||
slopeShape.rotation = new Vector3(0, 0, angle);
|
||
|
||
// 设置斜坡的物理材质
|
||
const material = new PhysicsMaterial();
|
||
material.staticFriction = 0.8; // 较大的摩擦力防止物体滑落
|
||
material.dynamicFriction = 0.8;
|
||
material.bounciness = 0.0;
|
||
slopeShape.material = material;
|
||
|
||
collider.addShape(slopeShape);
|
||
return entity;
|
||
}
|
||
```
|
||
|
||
4. **创建不同材质的复合形状**
|
||
```typescript
|
||
// 创建一个混合材质的平台
|
||
function createMixedPlatform(): Entity {
|
||
const entity = new Entity();
|
||
const collider = entity.addComponent(StaticCollider);
|
||
|
||
// 创建主平台(普通摩擦力)
|
||
const platformShape = new BoxColliderShape();
|
||
platformShape.size = new Vector3(10, 0.5, 10);
|
||
const normalMaterial = new PhysicsMaterial();
|
||
normalMaterial.staticFriction = 0.6;
|
||
normalMaterial.dynamicFriction = 0.6;
|
||
platformShape.material = normalMaterial;
|
||
collider.addShape(platformShape);
|
||
|
||
// 添加冰面区域(低摩擦力)
|
||
const iceShape = new BoxColliderShape();
|
||
iceShape.size = new Vector3(3, 0.51, 3);
|
||
iceShape.position = new Vector3(3, 0, 0);
|
||
const iceMaterial = new PhysicsMaterial();
|
||
iceMaterial.staticFriction = 0.1;
|
||
iceMaterial.dynamicFriction = 0.05;
|
||
iceShape.material = iceMaterial;
|
||
collider.addShape(iceShape);
|
||
|
||
// 添加弹性区域
|
||
const bounceShape = new BoxColliderShape();
|
||
bounceShape.size = new Vector3(3, 0.51, 3);
|
||
bounceShape.position = new Vector3(-3, 0, 0);
|
||
const bounceMaterial = new PhysicsMaterial();
|
||
bounceMaterial.bounciness = 0.8;
|
||
bounceMaterial.bounceCombine = PhysicsMaterialCombineMode.Maximum;
|
||
bounceShape.material = bounceMaterial;
|
||
collider.addShape(bounceShape);
|
||
|
||
return entity;
|
||
}
|
||
```
|
||
|
||
## 最佳实践
|
||
|
||
1. **形状选择**
|
||
- 复杂物体使用多个基础形状组合
|
||
- 避免使用过多的碰撞形状(影响性能)
|
||
- 为角色控制器选择胶囊体形状
|
||
|
||
2. **性能优化**
|
||
- 使用尽可能简单的碰撞形状
|
||
- 合理设置局部偏移,避免碰撞形状过度重叠
|
||
- 适当使用触发器代替实际的物理碰撞
|
||
- 及时销毁不再使用的碰撞形状及物理材质
|
||
|
||
|