轮廓间交互

⚠️ 轮廓间交互功能目前尚在Beta阶段,并且需要2.32.1及之后的基础库才能使用。

碰撞与重叠

碰撞和重叠是不同的概念:

  • 碰撞是指:两个轮廓发生物理学碰撞,并因此而改变位置与速度,产生碰撞事件;
  • 重叠是指:两个轮廓在位置上发生了重叠,并产生重叠事件,发生物理学碰撞。

需要轮廓才能发生交互

碰撞重叠是在两个轮廓之间发生的行为,所以在添加交互属性之前,请先确保为物体创建了轮廓。

轮廓交互组件

通过为标签添加shape-interact属性来设置轮廓间交互:

<xr-mesh ... mesh-shape shape-interact>

设置shape-interact属性后会自动为对应元素创建ShapeInteract组件。

组件属性

属性值 描述 值类型 备注
disabled 是否禁用交互 boolean disable=true的话,效果和不存在shape-interact属性时一致
collide 是否发生碰撞 boolean collide=true的话,发生碰撞,否则发生重叠,默认false
bounciness 弹性系数 number 0≤bounciness≤1,仅当collide=true时生效
staticFriction 静摩擦系数 number 0≤staticFriction≤1,仅当collide=true时生效
dynamicFriction 动摩擦系数 number 0≤staticFriction≤1,仅当collide=true时生效

⚠️ 只有两个物体的collide都为true,他们之间才能发生碰撞!

交互事件

在两个轮廓之间发生交互时,会产生交互事件,可以在标签上绑定相关绑定事件回调:

<xr-mesh ... mesh-shape shape-interact bind:overlap-begin="handleOverlapBegin">

事件一共有以下6种:

事件名 描述 事件回调参数
collide-begin 发生碰撞 ICollideEvent
collide-persist 碰撞持续 ICollideEvent
collide-exit 碰撞结束 ICollideEvent
overlap-begin 发生重叠 IOverlapEvent
overlap-persist 重叠持续 IOverlapEvent
overlap-exit 重叠结束 IOverlapEvent

其中xxx-begin和xxx-exit会成对地出现,从相交的第二帧开始xxx-persist每帧都会生成一次。

刚体和全局物理

⚠️ 刚体物理功能目前尚在Beta阶段,并且需要2.32.1及之后的基础库才能使用。

全局物理

要让当前的场景成为一个物理世界,需要先在<xr-scene>下配置一个<xr-physics>标签:

<xr-scene>
    <xr-physics />
    ...(场景中的其他标签)
</xr-scene>

⚠️ <xr-physics>标签只能位于<xr-scene>下一级,不能放置在更深的层级中。

全局物理配置

可以通过修改在<xr-physics>上的属性来配置全局物理参数(目前仅开放了少数配置项):

属性名 描述 值类型 备注
disabled 是否禁用物理 boolean disable=true的话,效果和不存在<xr-physics>标签时一致。
gravity 全局重力 Vector3 默认重力(0, -9.8, 0)

刚体

在标签上添加rigidbody属性来使其成为一个刚体:

<xr-mesh ... rigidbody />

添加之后就能观察到物体受重力影响而下落了。

刚体配置

通过为rigidbody属性添加属性值来修改刚体配置:

<xr-mesh ... rigidbody="mass: 5.0" />
属性值 描述 值类型 备注
disabled 是否禁用刚体 boolean disable=true的话,效果和不存在rigidbody属性时一致。
mass 刚体质量 number mass > 0
useGravity 是否受重力影响 boolean
constraintsMask 限制刚体在某个轴上的移动 number 具体指参考 @TODO

刚体组件

标签上的rigidbody属性对应元素上的Rigidbody组件。
使用Rigidbody组件上的方法可以移动刚体或者修改刚体属性:

方法名 描述 备注
addForce / addTorque 对刚体施加力,产生加速度。 对刚体施加力,产生加速度。
sleep / wakeUp 强制刚体睡眠/唤醒 正常情况下睡眠状态是由物理引擎自动管理的,如果发现刚体异常静止,可以尝试手动wakeUp。

轮廓

如果想要与场景中的物体进行互动,比如说点击、拖拽物体,那么这个物体得先拥有一个轮廓才行。

轮廓是一个组件。与某个物体互动,实际上是在与这个物体的轮廓进行互动,轮廓让这个物体在物理世界中拥有了一个分身。

创建轮廓

创建轮廓非常简单,只要为xml标签添加上xxx-shape的属性即可。
例如以下代码为一个球体创建了一个球状轮廓:

<xr-mesh node-id="mesh-sphere" geometry="sphere" sphere-shape></xr-mesh>

实际上,不需要标签是xr-mesh,任意一个场景标签都可以创建轮廓:

<xr-node node-id="shape-node" sphere-shape></xr-node>

轮廓种类

名称 标签属性名 组件数据 备注
球状轮廓 sphere-shape center, radius, autoFit
胶囊体轮廓 capsule-shape center, radius, height, autoFit
长方体轮廓 cube-shape center, size, autoFit
网格模型轮廓 mesh-shape 自动适配元素下的Mesh和GLTF模型

除了网格模型轮廓之外,其他轮廓均拥有autoFit属性(实际上网格模型轮廓的autoFit常开,所以不能设置)。开启autoFit之后,轮廓会自动寻找当前元素下的Mesh组件GLTF组件,并使用自身形状去尽量贴合模型。

如果将GLTF组件和开启了autoFit轮廓组合使用,那么会为GLTF内部的每个Mesh都创建一个轮廓。 ⚠️ 使用MeshShape的时候,请确保模型顶点数量小于65535个。如果超过了数量限制,推荐使用CubeShape+autoFit来代替。

轮廓交互

可以通过为标签绑定事件的方式来与轮廓进行互动,如果尚未了解如何绑定事件,可以参考事件文档。

例如使用以下代码,可以为轮廓绑定一个log事件(需自行完成logFunction函数):

<xr-node node-id="shape-node" cube-shape bind:touch-shape="logFunction"></xr-node>
事件名 描述 事件回调参数 备注
touch-shape 点击轮廓时触发 IShapeTouchEvent 如果有多个物体叠在一起,会点中最上层的。
drag-shape 点击轮廓后,手指不松开的情况下进行拖拽时触发 IShapeDragEvent 只有在先触发touch-shape之后才会触发这个事件,target和touch-shape保持一致。
untouch-shape 点击轮廓后,手指松开时触发 IShapeTouchEvent 只有在先触发touch-shape之后才会触发这个事件。

无论有没有绑定事件,其实都会触发事件,只是没有事件回调函数就什么都没发生。

轮廓可视化

为标签加上shape-gizmo即可将标签上的轮廓用线框绘制出来:

<xr-node node-id="shape-node" cube-shape shape-gizmo></xr-node>

MeshShape不会显示轮廓,因为基本上和渲染出来的模型一致。

物理系统

xr-frame中的物理系统主要管理场景中的轮廓,以及触发轮廓点击事件。


  • 轮廓 – 为物体创建可交互的轮廓;
  • 刚体和全局物理Beta – 让物体成为刚体,可以受到力的影响而产生加速度;
  • 轮廓间交互Beta – 让物体可以与其他物体产生交互,包括碰撞以及重叠判断。