Doc: physics collision layer (#2685)

* docs: add collision layer doc and opt characterController doc
This commit is contained in:
luzhuang
2025-05-23 13:48:31 +08:00
committed by GitHub
parent 9f7ea995d4
commit 5825a21dab
6 changed files with 301 additions and 55 deletions

View File

@@ -5,7 +5,26 @@ type: Physics
label: Physics
---
Character Controller ([CharacterController](/apis/core/#CharacterController)) is a special type of collider component specifically designed for handling character movement. It provides specialized movement algorithms and collision detection, capable of handling steps, slopes, and other complex terrains, making it particularly suitable for first-person or third-person game character control.
The [CharacterController](/apis/core/#CharacterController) is a special collider component designed specifically for handling character physics movement. It provides specialized movement algorithms and collision detection, capable of handling complex terrain like steps and slopes, making it particularly suitable for character control in first-person or third-person games.
## Differences from Dynamic Collider
While both the Character Controller and [Dynamic Collider](/docs/physics/collider/dynamicCollider) can achieve object movement, they have significant differences:
| Feature | Character Controller | Dynamic Collider |
|---------|---------------------|------------------|
| Movement Method | Direct displacement control via `move()` method | Movement through forces or impulses |
| Collision Response | Manual collision response, automatic step and slope handling | Physics-based collision response |
| Gravity Handling | Requires manual gravity implementation | Automatic scene gravity application |
| Shape Limitations | Can only use one collision shape | Can use multiple collision shapes |
| Use Cases | Character control, first/third-person games | Physics simulation, rigid body motion |
| Performance Cost | Lower | Higher |
<Callout type="positive">
Recommendations:
- Use Character Controller when precise control over character movement and collision response is needed
- Use Dynamic Collider when realistic physics simulation is required
</Callout>
## Usage
@@ -13,55 +32,53 @@ Character Controller ([CharacterController](/apis/core/#CharacterController)) is
<Image src="https://mdn.alipayobjects.com/huamei_3zduhr/afts/img/A*nEMXRKiqpy8AAAAAAAAAAAAAesJ_AQ/original" />
2. Set the collision shape of the controller to match the character's appearance as closely as possible. For detailed instructions on collision shapes, please refer to the [Collision Shape](/docs/physics/collider/colliderShape) documentation.
2. Set the controller's collision shape to match the character's appearance as closely as possible. For detailed information about collision shapes, please refer to the [ColliderShape](/docs/physics/collider/colliderShape) documentation.
<Callout type="positive">
Unlike other colliders, the character controller can only add one collision shape. It is generally recommended to use a capsule shape (CapsuleColliderShape) as the character's collision shape.
Unlike other colliders, the Character Controller can only have one collision shape. It is recommended to use a CapsuleColliderShape as the character's collision shape.
</Callout>
<Image src="https://mdn.alipayobjects.com/huamei_3zduhr/afts/img/A*4QvUTI4D89EAAAAAAAAAAAAAesJ_AQ/original" />
<Image src="https://mdn.alipayobjects.com/huamei_3zduhr/afts/img/A*aRGqSIMqDmsAAAAAAAAAAAAAesJ_AQ/original" />
3. Adjust the properties of the collider as needed to modify the physical behavior of the object. The meaning and function of each property are explained below.
3. Adjust the collider's properties according to your needs to modify the object's physical behavior. The meaning and function of each property are explained below.
## Property Explanation
## Property Description
### Inherited from Collider
| Property | Description |
| ----------------------------------------- | ----------------- |
### Properties Inherited from Collider
| Property | Description |
|----------|-------------|
| [**shapes**](/apis/core/#Collider-shapes) | Collection of collision shapes |
### CharacterController Specific Properties
| Property | Description | Default Value |
| ---- | ---- | ------ |
| [**stepOffset**](/apis/core/#CharacterController-stepOffset) | The maximum step height the character can automatically step over. <ul><li>Must be greater than or equal to 0</li><li>Actual step height = stepOffset + contact offset of the collision shape</li></ul> | 0.5 |
| [**slopeLimit**](/apis/core/#CharacterController-slopeLimit) | The maximum slope angle (degrees) the character can walk on. <ul><li>Slopes steeper than this angle will be treated as walls</li><li>Affects the character's ability to climb slopes</li></ul> | 45° |
| [**nonWalkableMode**](/apis/core/#CharacterController-nonWalkableMode) | Defines how to handle non-walkable surfaces. <ul><li>PreventClimbing: Prevents the character from climbing non-walkable slopes but does not force other movements (default)</li><li>PreventClimbingAndForceSliding: Prevents the character from climbing non-walkable slopes and forces the character to slide down the slope</li></ul> | PreventClimbing |
| [**upDirection**](/apis/core/#CharacterController-upDirection) | Defines the upward direction of the character. The default is (0, 1, 0), which is the Y-axis in world space. Affects the direction determination for movement and collision detection | (0, 1, 0) |
### Specific Properties
| Property | Description | Default |
|----------|-------------|---------|
| [**stepOffset**](/apis/core/#CharacterController-stepOffset) | Maximum step height the character can automatically climb.<ul><li>Must be greater than or equal to 0</li><li>Actual climbable height = stepOffset + contact offset of collision shape</li></ul> | 0.5 |
| [**slopeLimit**](/apis/core/#CharacterController-slopeLimit) | Maximum slope angle (in degrees) the character can walk on.<ul><li>Surfaces steeper than this angle will be treated as unwalkable walls</li><li>Affects the character's climbing ability</li></ul> | 45° |
| [**nonWalkableMode**](/apis/core/#CharacterController-nonWalkableMode) | Defines how to handle unwalkable surfaces.<ul><li>PreventClimbing: Prevents the character from climbing unwalkable slopes but doesn't force other movements (default)</li><li>PreventClimbingAndForceSliding: Prevents the character from climbing unwalkable slopes and forces the character to slide down</li></ul> | PreventClimbing |
| [**upDirection**](/apis/core/#CharacterController-upDirection) | Defines the character's up direction. Default is (0, 1, 0), which means Y-axis up in world space. Affects movement and collision detection direction | (0, 1, 0) |
## Methods
## Public Methods
### Inherited from Collider
| Method Name | Description |
| --------------------------------------------------- | ----------------- |
| [**addShape**](/apis/core/#Collider-addShape) | Add a collision shape |
### Methods Inherited from Collider
| Method | Description |
|--------|-------------|
| [**addShape**](/apis/core/#Collider-addShape) | Add a collision shape |
| [**removeShape**](/apis/core/#Collider-removeShape) | Remove a specified collision shape |
| [**clearShapes**](/apis/core/#Collider-clearShapes) | Clear all collision shapes |
### CharacterController Specific Methods
| Method Name | Description |
| ---- | ---- |
| [**move**](/apis/core/#CharacterController-move) | Moves the character controller. Returns a collision flag value indicating the collision state. <ul><li>displacement: Movement vector</li><li>minDist: Minimum movement distance</li><li>elapsedTime: Elapsed time</li></ul> |
### Specific Methods
| Method | Description |
|--------|-------------|
| [**move**](/apis/core/#CharacterController-move) | Move the character controller. Returns a collision flag value indicating collision status.<ul><li>displacement: Movement vector</li><li>minDist: Minimum movement distance</li><li>elapsedTime: Elapsed time</li></ul> |
### Collision Flags
The `move()` function returns a collision flag value that indicates the collision state of the character controller with the environment. These flags can be checked using bitwise AND operations (&):
The `move()` function returns a collision flag value that indicates the character controller's collision status with the environment. These flags can be detected using bitwise AND operations (&):
| Flag Name | Value | Description |
|---------|----|----|
|-----------|-------|-------------|
| None | 0 | No collision occurred |
| Sides | 1 | Collided with sides |
| Up | 2 | Collided with the top (e.g., ceiling) |
@@ -91,9 +108,8 @@ controller.upDirection = new Vector3(0, 1, 0); // Set upward direction
class CharacterMovement extends Script {
private _velocity = new Vector3();
onUpdate() {
onUpdate(deltaTime: number) {
const controller = this.entity.getComponent(CharacterController);
const deltaTime = engine.deltaTime;
// Create displacement vector
const displacement = new Vector3();
@@ -112,17 +128,6 @@ class CharacterMovement extends Script {
}
```
### Collision Flags
The `move()` function returns a collision flag value indicating the character controller's collision state with the environment. These flags can be checked using bitwise AND (&) operations:
| Flag Name | Value | Description |
|---------|----|----|
| None | 0 | No collision occurred |
| Sides | 1 | Collision with sides |
| Up | 2 | Collision with ceiling |
| Down | 4 | Collision with ground |
Usage example:
```typescript
const flags = controller.move(displacement, 0, deltaTime);
@@ -139,36 +144,106 @@ if (flags & ControllerCollisionFlag.Up) {
this._velocity.y = 0;
}
// Check if hitting walls
// Check if hitting wall
if (flags & ControllerCollisionFlag.Sides) {
// Character hit wall
this._handleWallCollision();
}
// Check multiple flags
// Can check multiple flags simultaneously
if ((flags & ControllerCollisionFlag.Down) &&
(flags & ControllerCollisionFlag.Sides)) {
// Character is touching both ground and wall
}
```
### Walking on Slopes/Steps
### Slope/Step Walking
1. **Walking on Slopes**
1. **Slope Walking**
```typescript
// Control the walkable slope angle by setting slopeLimit
// Control walkable slope angle by setting slopeLimit
controller.slopeLimit = 60; // Allow steeper slopes
// Set the handling method for non-walkable slopes
controller.nonWalkableMode = ControllerNonWalkableMode.PreventClimbingAndForceSliding; // Slide down steep slopes
// Set how to handle unwalkable slopes
controller.nonWalkableMode = ControllerNonWalkableMode.PreventClimbingAndForceSliding; // Will slide down on too steep slopes
```
2. **Adjusting Step Height**
2. **Step Walking Adjustment**
```typescript
// Adjust stepOffset to control the maximum step height
// Adjust stepOffset to control climbable step height
controller.stepOffset = 0.3; // Lower steps
controller.stepOffset = 0.5; // Higher steps
```
For a complete example, refer to:
### Gravity Handling
The Character Controller itself doesn't include gravity handling; you need to implement gravity effects manually in scripts. Here's a complete gravity handling example:
```typescript
class CharacterMovement extends Script {
private _controller: CharacterController;
private _velocity = new Vector3();
private _isGrounded = false;
private _moveSpeed = 5;
private _jumpForce = 5;
private _gravity: Vector3;
onAwake() {
this._controller = this.entity.getComponent(CharacterController);
this._gravity = this.scene.physics.gravity;
}
onUpdate(deltaTime: number) {
const inputManager = this.engine.inputManager;
// Get input
const horizontal = inputManager.isKeyHeldDown(Keys.KeyA) ? -1 : inputManager.isKeyHeldDown(Keys.KeyD) ? 1 : 0;
const vertical = inputManager.isKeyHeldDown(Keys.KeyS) ? -1 : inputManager.isKeyHeldDown(Keys.KeyW) ? 1 : 0;
const jump = inputManager.isKeyDown(Keys.Space);
// Calculate movement direction
const moveDirection = new Vector3(horizontal, 0, vertical);
moveDirection.normalize();
// Apply movement speed
this._velocity.x = moveDirection.x * this._moveSpeed;
this._velocity.z = moveDirection.z * this._moveSpeed;
// Apply gravity
if (!this._isGrounded) {
this._velocity.y += this._gravity.y * deltaTime;
}
// Handle jumping
if (this._isGrounded && jump) {
this._velocity.y = this._jumpForce;
this._isGrounded = false;
}
// Execute movement
const displacement = new Vector3();
Vector3.scale(this._velocity, deltaTime, displacement);
const collisionFlags = this._controller.move(displacement, 0, deltaTime);
// Update ground status
this._isGrounded = (collisionFlags & ControllerCollisionFlag.Down) !== 0;
if (this._isGrounded) {
this._velocity.y = 0;
}
}
}
```
## Limitations and Considerations
1. **Shape Limitations**
- Can only use one collision shape
- Recommended to use CapsuleColliderShape as the collision shape
2. **Performance Considerations**
- Character Controller has better performance than Dynamic Collider
- But each Character Controller consumes some physics calculation resources
- It's recommended to control the number of Character Controllers in the scene
For a complete example, please refer to:
<Playground href="/embed/physx-controller" />

View File

@@ -0,0 +1,38 @@
---
order: 6
title: Collision Layer
type: Physics
label: Physics
---
Collision Layer is an important concept in the physics system that controls collision relationships between different objects. By setting collision layers, you can flexibly control which objects can collide with each other and which cannot.
## Setting Collision Layers
Each [collider](/docs/physics/collider/overview) can be assigned to a collision layer. The engine provides 32 collision layers (Layer0 to Layer31), and each collider can only belong to one layer.
```typescript
// Set collider to Layer1
collider.collisionLayer = Layer.Layer1;
```
## Configuring Collision Relationships
The collision relationships between layers can be set using the `setColliderLayerCollision` method of [PhysicsScene](/apis/core/#PhysicsScene) to determine whether collisions can occur between two layers:
```typescript
// Disable collision between Layer1 and Layer2
scene.physics.setColliderLayerCollision(Layer.Layer1, Layer.Layer2, false);
// Enable collision between Layer1 and Layer2
scene.physics.setColliderLayerCollision(Layer.Layer1, Layer.Layer2, true);
// Check collision relationship between Layer1 and Layer2
console.log(scene.physics.getColliderLayerCollision(Layer.Layer1, Layer.Layer2));
```
## Important Notes
1. Each collider can only belong to one collision layer
2. By default, collisions can occur between all collision layers
3. Collision layer settings affect both physical collisions and trigger events

View File

@@ -1,5 +1,5 @@
---
order: 1
order: 0
title: Collider
type: Physics
label: Physics
@@ -44,6 +44,9 @@ Currently, four types of `collision shapes` are supported, but the support varie
- `Collision shapes` can be set with local offsets and rotations relative to the entity
3. **Collision/Trigger Events**: Colliders can generate collision and trigger events when interacting with other colliders. For detailed information on these events and how to handle them, please refer to the [Collision Events](/docs/physics/collider/event) documentation.
4. **Collision Layer**: Each collider can be assigned to a collision layer (Layer0 to Layer31), which is used to control collision relationships between different objects. By setting collision layers, you can flexibly control which objects can collide with each other and which cannot. For more information, please refer to the [Collision Layer](/docs/physics/collider/collisionLayer) documentation.
## Best Practices
1. **Reasonable Use of Shapes**
@@ -99,3 +102,4 @@ const characterController = entity.addComponent(CharacterController);
- [Static Collider Documentation](/docs/physics/collider/staticCollider)
- [Character Controller Documentation](/docs/physics/collider/characterController)
- [Collision Events Documentation](/docs/physics/collider/event)
- [Collision Layer Documentation](/docs/physics/collider/collisionLayer)

View File

@@ -7,6 +7,25 @@ label: Physics
角色控制器([CharacterController](/apis/core/#CharacterController))是一种特殊的碰撞器组件,专门用于处理角色的物理运动。它提供了专门的移动算法和碰撞检测,能够处理台阶、斜坡等复杂地形,特别适合第一人称或第三人称游戏中的角色控制。
## 与动态碰撞器的区别
角色控制器和[动态碰撞器](/docs/physics/collider/dynamicCollider)虽然都可以实现物体的移动,但它们有着显著的区别:
| 特性 | 角色控制器 | 动态碰撞器 |
|------|------------|------------|
| 移动方式 | 通过 `move()` 方法直接控制位移 | 通过施加力或冲量来移动 |
| 碰撞响应 | 手动处理碰撞响应,自动处理台阶和斜坡 | 基于物理模拟的碰撞响应 |
| 重力处理 | 需要手动实现重力效果 | 自动应用场景重力 |
| 形状限制 | 只能使用一个碰撞形状 | 可以使用多个碰撞形状 |
| 适用场景 | 角色控制、第一/第三人称游戏 | 物理模拟、刚体运动 |
| 性能开销 | 较低 | 较高 |
<Callout type="positive">
选择建议:
- 如果需要精确控制角色的移动和碰撞响应,使用角色控制器
- 如果需要真实的物理模拟效果,使用动态碰撞器
</Callout>
## 使用方法
1. 选中目标实体,并在检查器中点击添加组件按钮,添加 CharacterController 组件。
@@ -91,9 +110,8 @@ controller.upDirection = new Vector3(0, 1, 0); // 设置向上方向
class CharacterMovement extends Script {
private _velocity = new Vector3();
onUpdate() {
onUpdate(deltaTime: number) {
const controller = this.entity.getComponent(CharacterController);
const deltaTime = engine.deltaTime;
// 创建位移向量
const displacement = new Vector3();
@@ -159,5 +177,75 @@ controller.stepOffset = 0.3; // 较低的台阶
controller.stepOffset = 0.5; // 较高的台阶
```
### 重力处理
角色控制器本身不包含重力处理,需要在脚本中手动实现重力效果。以下是一个完整的重力处理示例:
```typescript
class CharacterMovement extends Script {
private _controller: CharacterController;
private _velocity = new Vector3();
private _isGrounded = false;
private _moveSpeed = 5;
private _jumpForce = 5;
private _gravity: Vector3;
onAwake() {
this._controller = this.entity.getComponent(CharacterController);
this._gravity = this.scene.physics.gravity;
}
onUpdate(deltaTime: number) {
const inputManager = this.engine.inputManager;
// 获取输入
const horizontal = inputManager.isKeyHeldDown(Keys.KeyA) ? -1 : inputManager.isKeyHeldDown(Keys.KeyD) ? 1 : 0;
const vertical = inputManager.isKeyHeldDown(Keys.KeyS) ? -1 : inputManager.isKeyHeldDown(Keys.KeyW) ? 1 : 0;
const jump = inputManager.isKeyDown(Keys.Space);
// 计算移动方向
const moveDirection = new Vector3(horizontal, 0, vertical);
moveDirection.normalize();
// 应用移动速度
this._velocity.x = moveDirection.x * this._moveSpeed;
this._velocity.z = moveDirection.z * this._moveSpeed;
// 应用重力
if (!this._isGrounded) {
this._velocity.y += this._gravity.y * deltaTime;
}
// 处理跳跃
if (this._isGrounded && jump) {
this._velocity.y = this._jumpForce;
this._isGrounded = false;
}
// 执行移动
const displacement = new Vector3();
Vector3.scale(this._velocity, deltaTime, displacement);
const collisionFlags = this._controller.move(displacement, 0, deltaTime);
// 更新地面状态
this._isGrounded = (collisionFlags & ControllerCollisionFlag.Down) !== 0;
if (this._isGrounded) {
this._velocity.y = 0;
}
}
}
```
## 限制和注意事项
1. **形状限制**
- 只能使用一个碰撞形状
- 建议使用胶囊体CapsuleColliderShape作为碰撞形状
2. **性能考虑**
- 角色控制器比动态碰撞器性能更好
- 但每个角色控制器都会占用一定的物理计算资源
- 建议在场景中控制角色控制器的数量
完整的示例效果可以参考:
<Playground href="/embed/physx-controller" />

View File

@@ -0,0 +1,38 @@
---
order: 6
title: 碰撞层
type: 物理
label: Physics
---
碰撞层Collision Layer是物理系统中的一个重要概念用于控制不同物体之间的碰撞关系。通过设置碰撞层可以灵活地控制哪些物体之间可以发生碰撞哪些物体之间不能发生碰撞。
## 碰撞层设置
每个[碰撞器](/docs/physics/collider/overview)都可以被分配到一个碰撞层。引擎提供了 32 个碰撞层Layer0 到 Layer31每个碰撞器只能属于一个碰撞层。
```typescript
// 设置碰撞器到 Layer1
collider.collisionLayer = Layer.Layer1;
```
## 碰撞关系设置
碰撞层之间的碰撞关系可以使用 [PhysicsScene](/apis/core/#PhysicsScene) 的 `setColliderLayerCollision` 方法来设置两个碰撞层之间是否可以发生碰撞:
```typescript
// 禁用 Layer1 和 Layer2 之间的碰撞
scene.physics.setColliderLayerCollision(Layer.Layer1, Layer.Layer2, false);
// 启用 Layer1 和 Layer2 之间的碰撞
scene.physics.setColliderLayerCollision(Layer.Layer1, Layer.Layer2, true);
// 查看 Layer1 和 Layer2 之间的碰撞关系
console.log(scene.physics.getColliderLayerCollision(Layer.Layer1, Layer.Layer2));
```
## 注意事项
1. 每个碰撞器只能属于一个碰撞层
2. 默认情况下,所有碰撞层之间都可以发生碰撞
3. 碰撞层设置会同时影响物理碰撞和触发器事件

View File

@@ -1,5 +1,5 @@
---
order: 1
order: 0
title: 碰撞器
type: 物理
label: Physics
@@ -45,6 +45,8 @@ label: Physics
3. **碰撞/触发事件**:碰撞器在与其他碰撞器交互时可以生成碰撞和触发器事件。有关这些事件的详细信息以及如何处理它们,请参阅[碰撞事件](/docs/physics/collider/event)文档。
4. **碰撞层**每个碰撞器可以被分配到一个碰撞层Layer0 到 Layer31用于控制不同物体之间的碰撞关系。通过设置碰撞层可以灵活地控制哪些物体之间可以发生碰撞哪些物体之间不能发生碰撞。更多信息请参考[碰撞层](/docs/physics/collider/collisionLayer)文档。
## 最佳实践
1. **合理使用形状**
@@ -101,3 +103,4 @@ const characterController = entity.addComponent(CharacterController);
- [静态碰撞器文档](/docs/physics/collider/staticCollider)
- [角色控制器文档](/docs/physics/collider/characterController)
- [碰撞事件文档](/docs/physics/collider/event)
- [碰撞层文档](/docs/physics/collider/collisionLayer)