Physics
Dynamic Collider
Dynamic Collider (DynamicCollider) is used to simulate objects that can move freely and are affected by physical forces. It can respond to gravity, forces, collisions, and other physical effects, suitable for game objects that require realistic physical simulation.
- Select the target entity and click the Add Component button in the inspector to add the DynamicCollider component.
- Add a collision shape to the collider. Dynamic colliders support adding multiple collision shapes. For detailed instructions on collision shapes, please refer to the Collision Shape documentation. Currently, the following types are supported:
- Adjust the position, size, and other properties of the collision shape to match the scene elements.
- 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.
Property | Description |
---|
shapes | Collection of collision shapes |
Property | Description | Default Value |
---|
mass | Mass of the collider. The larger the mass, the harder it is to change the object's motion state | 1.0 |
useGravity | Whether to be affected by gravity | true |
isKinematic | Whether it is a kinematic object. Kinematic objects are not affected by physics but can affect other objects | false |
Property | Description | Default Value |
---|
centerOfMass | Position of the center of mass relative to the transform origin | (0,0,0) |
automaticCenterOfMass | Whether to automatically calculate the center of mass | true |
inertiaTensor | Inertia tensor of the object relative to the center of mass | (1,1,1) |
automaticInertiaTensor | Whether to automatically calculate the inertia tensor | true |
Property | Description | Default Value |
---|
sleepThreshold | Sleep threshold. Objects enter sleep mode when their motion energy falls below this value | 0.005 |
solverIterations | Constraint solver iteration count | 4 |
Constraint solving is the process used by the physics engine to resolve collisions and constraints between objects. Each iteration attempts to adjust the positions and velocities of objects to satisfy all physical constraints (such as collisions, joints, etc.).
- More iterations result in more accurate physical behavior but higher computational cost
- Too few iterations may cause objects to jitter or penetrate
- It is recommended to balance accuracy and performance based on actual needs:
- General objects: Use the default value of 4
- Precise physics: Increase to 6-8
- Performance priority: Reduce to 2-3
- constraints
Used to restrict the object's movement along specific axes. You can lock position and rotation along the X, Y, and Z axes.
// Lock Y-axis position and all rotations
collider.constraints =
DynamicColliderConstraints.FreezePositionY |
DynamicColliderConstraints.FreezeRotationX |
DynamicColliderConstraints.FreezeRotationY |
DynamicColliderConstraints.FreezeRotationZ;
Mode | Description | Applicable Scenarios | Performance Cost |
---|
Discrete | Basic detection mode, detects collisions at fixed time steps, may cause tunneling at high speeds | Low-speed objects | Lowest |
Continuous | Continuous detection for static colliders, prevents high-speed objects from tunneling through static objects | High-speed projectiles | Moderate |
ContinuousDynamic | Continuous detection for all colliders, prevents high-speed objects from tunneling through each other | Precise physical simulations | High |
ContinuousSpeculative | Uses speculative algorithms for continuous detection, performance cost between Discrete and Continuous | General game scenarios | Moderate |
// 1. Use discrete detection for normal objects
normalObject.collisionDetectionMode = CollisionDetectionMode.Discrete;
// 2. Use continuous detection for projectiles to prevent tunneling
projectile.collisionDetectionMode = CollisionDetectionMode.Continuous;
// 3. Use fully continuous detection for important physical interactions
importantPhysicsObject.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
// 4. Use speculative detection for general game objects
gameObject.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative;
-
Based on Object Speed
- Low-speed objects: Use Discrete
- Medium-speed objects: Use ContinuousSpeculative
- High-speed objects: Use Continuous or ContinuousDynamic
-
Based on Importance
- Normal scene objects: Use Discrete
- Critical game objects: Use ContinuousSpeculative
- Precise physical interactions: Use ContinuousDynamic
-
Based on Performance
- Performance priority: Use Discrete
- Balance between performance and precision: Use ContinuousSpeculative
- Precision priority: Use ContinuousDynamic
// Create dynamic collider
const dynamicCollider = entity.addComponent(DynamicCollider);
// Add collision shape
const boxShape = new BoxColliderShape();
boxShape.size = new Vector3(1, 1, 1);
dynamicCollider.addShape(boxShape);
// Configure basic physical properties
dynamicCollider.mass = 1.0; // Set mass
dynamicCollider.useGravity = true; // Enable gravity
dynamicCollider.isKinematic = false; // Set to dynamic mode
class PhysicsController extends Script {
private _collider: DynamicCollider;
onAwake() {
// Get dynamic collider reference
this._collider = this.entity.getComponent(DynamicCollider);
// Configure motion damping
this._collider.linearDamping = 0.1; // Set linear damping
this._collider.angularDamping = 0.1; // Set angular damping
// Set motion constraints
this._collider.constraints =
DynamicColliderConstraints.FreezeRotationX | // Lock X-axis rotation
DynamicColliderConstraints.FreezeRotationZ; // Lock Z-axis rotation
}
onUpdate() {
// Get current velocity
const velocity = this._collider.linearVelocity;
// Set velocity
this._collider.linearVelocity = new Vector3(5, velocity.y, 0);
// Apply continuous force (e.g., thrust)
if (this.engine.inputManager.isKeyHeldDown(Keys.W)) {
this._collider.applyForce(new Vector3(0, 0, 10));
}
// Apply instantaneous force (e.g., jump)
if (this.engine.inputManager.isKeyDown(Keys.Space)) {
this._collider.applyForce(new Vector3(0, 500, 0));
}
// Apply torque (e.g., rotation)
if (this.engine.inputManager.isKeyHeldDown(Keys.R)) {
this._collider.applyTorque(new Vector3(0, 10, 0));
}
}
}
class KinematicController extends Script {
private _collider: DynamicCollider;
onAwake() {
this._collider = this.entity.getComponent(DynamicCollider);
this._collider.isKinematic = true; // Set to kinematic mode
}
// Implement elevator movement
onUpdate() {
const time = this.engine.time.elapsedTime;
const position = new Vector3(0, Math.sin(time) * 2, 0);
this._collider.move(position);
}
}
class SleepController extends Script {
private _collider: DynamicCollider;
onAwake() {
this._collider = this.entity.getComponent(DynamicCollider);
// Configure sleep parameters
this._collider.sleepThreshold = 0.005; // Set sleep threshold
}
onUpdate() {
// Check if the object is sleeping
if (this._collider.isSleeping()) {
console.log("Object is sleeping");
}
// Manually control sleep
if (this.engine.inputManager.isKeyDown(Keys.S)) {
this._collider.sleep(); // Force sleep
}
if (this.engine.inputManager.isKeyDown(Keys.W)) {
this._collider.wakeUp(); // Wake up the object
}
}
}
// Automatic calculation
const collider = entity.addComponent(DynamicCollider);
collider.mass = 1.0;
collider.automaticCenterOfMass = true; // Automatically calculate center of mass
collider.automaticInertiaTensor = true; // Automatically calculate inertia tensor
// Manual settings
const customCollider = entity.addComponent(DynamicCollider);
customCollider.automaticCenterOfMass = false;
customCollider.automaticInertiaTensor = false;
customCollider.centerOfMass = new Vector3(0, 0.5, 0); // Manually set center of mass
customCollider.inertiaTensor = new Vector3(1, 1, 1); // Manually set inertia tensor