Skip to content
本页内容

碰撞体

碰撞体定义物体响应碰撞的实际物理性状,通常在渲染层是不可见的。通过碰撞体组件的设定,物理系统可以判定两个物体是否相交,从而产生碰撞效果。

碰撞体组件概览

我们封装了以下几个常见的碰撞体形状类型,方便用户使用:

  1. 盒型碰撞体

Box Collider

ts
import { BoxColliderShape } from '@orillusion/physics'

// some codes here to create object...
let collider = object.addComponent(Collider);
collider.shape = new BoxColliderShape();
// set shape parameters...
collider.shape.size = new Vector3(2, 2, 2);
参数类型描述
sizeVecter3盒型碰撞体的大小。默认以物体中心为长方体中心,通过新建Vecter3实例分别指定长方体沿x、y、z坐标轴的长度大小
  1. 球形碰撞体

Sphere Collider

ts
import { SphereColliderShape } from '@orillusion/physics'

// some codes here to create object...
let collider = object.addComponent(Collider);
collider.shape = new SphereColliderShape();
// set shape parameters...
collider.radius = 5;
参数类型描述
radiusnumber球形碰撞体的半径。默认以物体中心为球体中心
  1. 胶囊碰撞体

Capsule Collider

ts
import { CapsuleColliderShape } from '@orillusion/physics'

// some codes here to create object...
let collider = object.addComponent(Collider);
collider.shape = new CapsuleColliderShape();
// set shape parameters...
collider.radius = 2.5;
collider.height = 10;
参数类型描述
radiusnumber胶囊碰撞体上下半球体的半径
heightnumber胶囊碰撞体的高度,默认以物体中心为胶囊体中心

碰撞体组件应用示例

在为对象添加了刚体组件后,我们再为它添加一个碰撞体,并指定碰撞体的形状类型,便可以让该对象响应碰撞了:

ts
import { Vecter3D, Object3D } from '@orillusion/core'
import { BoxColliderShape, Rigidbody } from '@orillusion/physics'

let object = new Object3D();
object.addComponent(Rigidbody);
let collider = obj.addComponent(Collider);
collider.shape = new BoxColliderShape();
collider.shape.size = new Vector3(2, 2, 2);

利用碰撞组件,我们可以模拟出逼真的物理效果,下面我们通过展示一个更复杂的示例,进一步了解物理系统可以实现的效果。


Orillusion powered by WebGPU on Chrome/Edge 113+
Please upgrade to latest Chrome/Edge

<
ts
import { BoxColliderShape, BoxGeometry, Camera3D, Collider, Color, ComponentBase, DirectLight, Engine3D, ForwardRenderJob, LitMaterial, HoverCameraController, MeshRenderer, Object3D, PlaneGeometry, Scene3D, Vector2, Vector3 } from "@orillusion/core";
import { Physics, Rigidbody } from "@orillusion/physics";

export class Sample_colliders {
  constructor() {}

  addPlane (scene: Scene3D, size: Vector2, pos: Vector3, rot: Vector3) {
    // 新建对象
    const obj = new Object3D();
    // 为对象添 MeshRenderer
    let mr = obj.addComponent(MeshRenderer);
    // 设置几何体
    //mr.geometry = new CubeGeometry(10, 10, 10)
    mr.geometry = new PlaneGeometry(size.x, size.y);
    // 设置材质
    mr.material = new LitMaterial();
    mr.material.baseColor = new Color(0.04, 0.42, 0.45, 1);
    // 设置缩放
    obj.localPosition = pos;
    obj.localRotation = rot;
    // 添加刚体碰撞体
    let rigidbody = obj.addComponent(Rigidbody);
    rigidbody.mass = 0;
    let collider = obj.addComponent(Collider);
    collider.shape = new BoxColliderShape();
    collider.shape.size = new Vector3(size.x, 0.1, size.y);

    scene.addChild(obj);

    return obj;
  }

  loop() {
    if (Physics.isInited) {
      Physics.update();
    }
  }

  async run() {
    await Physics.init();
    // 初始化引擎环境;
    await Engine3D.init({
      renderLoop: () => this.loop()
    });

    let scene3D = new Scene3D();
    // 新建摄像机实例
    let cameraObj = new Object3D();
    let mainCamera = cameraObj.addComponent(Camera3D);
    // 调整摄像机视角
    mainCamera.lookAt(new Vector3(0, 0, 10), new Vector3(0, 0, 0));
    mainCamera.perspective(60, window.innerWidth / window.innerHeight, 1, 5000.0);
    let controller = mainCamera.object3D.addComponent(HoverCameraController);
    controller.setCamera(45, -15, 150, new Vector3(0, 30, 0));
    // 添加相机节点
    scene3D.addChild(cameraObj);

    // 新建光照
    let light: Object3D = new Object3D();
    // 添加直接光组件
    let component = light.addComponent(DirectLight);
    // 调整光照参数
    light.rotationX = 45;
    light.rotationY = 30;
    component.lightColor = new Color(1.0, 1.0, 1.0, 1.0);
    component.intensity = 1;
    // 添加光照对象
    scene3D.addChild(light);

    this.addPlane(scene3D, new Vector2(100, 100), new Vector3(0, 0, 0), new Vector3(0, 0, 0))
    scene3D.addComponent(BoxGenerator);

    // 新建前向渲染业务
    let renderJob = new ForwardRenderJob(scene3D);
    // 开始渲染
    Engine3D.startRender(renderJob);
  }
}

class BoxGenerator extends ComponentBase {
  // 记录添加桌子的间隔时间
  private _lastTime: number = performance.now()

  // 脚本更新回调
  public update(): void {
    // 计算新的间隔时间
    let now: number = performance.now()
    // 每间隔300ms,添加一个桌子
    if (now - this._lastTime > 300) {
      // 添加桌子
      this._addBox();
      // 删除最早的物体,保持场景数量
      if(this.object3D.entityChildren.length > 500)
        this.object3D.removeChildByIndex(4)
      // 重置间隔时间
      this._lastTime = now;
    }
  }

  // 添加桌子的函数
  private _addBox(): void {
    // 新建对象
    const obj = new Object3D();
    // 为对象添 MeshRenderer
    let mr = obj.addComponent(MeshRenderer);
    // 设置几何体
    mr.geometry = new BoxGeometry(5, 5, 5);
    // 设置材质
    mr.material = new LitMaterial();
    mr.material.baseColor = new Color(Math.random(), Math.random(), Math.random(), 1.0);
    // 设置位置旋转
    obj.localPosition = new Vector3(Math.random() * 70 - 35, 50, Math.random() * 70 - 35)
    obj.localRotation = new Vector3(Math.random() * 360, Math.random() * 360, Math.random() * 360)
    // 添加刚体碰撞体
    let rigidbody = obj.addComponent(Rigidbody);
    rigidbody.mass = 10;
    let collider = obj.addComponent(Collider);
    collider.shape = new BoxColliderShape();
    collider.shape.size = new Vector3(5, 5, 5);

    this.object3D.addChild(obj);
  }
}

new Sample_colliders().run();