物理
PlayCanvas 的物理系统支持重力、碰撞、力和约束,由 ammo.js 驱动。
入门
ammo.js 是 WASM 库,在 React 中按需加载,只有需要时才分发,可减小初始包。也可先渲染内容,再等待物理,或由交互触发加载,尽快显示场景。
先安装 sync-ammo:
npm install sync-ammo
再为根 Application 添加 usePhysics:
提示
仅设置 usePhysics 时才加载 ammo.js。
<Application usePhysics>
<Entity>
<Rigidbody type="box" />
</Entity>
</Application>
用法
给实体添加 RigidBody 和 Collision 即参与模拟。下例创建静态地面、下落球体和盒体:
- 演示
- 代码
basic-physics.jsx
// ↑ imports hidden
export const BasicPhysics = () => {
const sphereMaterial = useMaterial({ diffuse: 'red' });
const boxMaterial = useMaterial({ diffuse: '#4ecdc4' });
return (<>
{/* Ground (static) */}
<Entity name="ground" position={[0, -0.6, 0]} scale={[100, 0.1, 100]}>
<RigidBody type="static" friction={0.5} />
<Collision type="box" halfExtents={[50, 0.1, 50]} />
</Entity>
{/* Falling sphere */}
<Entity name="sphere" position={[0, 6, 0]}>
<RigidBody type="dynamic" mass={1} />
<Collision type="sphere" />
<Render type="sphere" material={sphereMaterial} />
</Entity>
{/* Falling box */}
<Entity name="box"
position={[0.1, 8, 0]}
rotation={[math.random(0, 360), math.random(0, 360), math.random(0, 360)]}
>
<RigidBody type="dynamic" mass={2} />
<Collision type="box" />
<Render type="box" material={boxMaterial} />
</Entity>
</>);
};
物理属性
<RigidBody
type="dynamic"
mass={1} // Object mass
linearDamping={0.1} // Air resistance for movement
angularDamping={0.1} // Air resistance for rotation
friction={0.5} // Surface friction
restitution={0.3} // Bounciness (0 = no bounce, 1 = perfect bounce)
/>
<Collision
type="box"
halfExtents={[1, 1, 1]} // Size for box collision
radius={0.5} // Radius for sphere/cylinder collision
height={2} // Height for capsule/cylinder collision
/>
usePhysics Hook
物理引擎异步创建,可用 usePhysics 响应其状态。
import { usePhysics } from '@playcanvas/react/hooks';
const PhysicsStatus = () => {
const { isPhysicsEnabled, isPhysicsLoaded, physicsError } = usePhysics();
// ...
};
状态信息和接口详见 usePhysics。
更完整内容见物理手册。
故障排查
webpack 提示无法解析 sync-ammo
sync-ammo 是可选依赖,仅物理需要。未安装时,webpack,包括 next build --webpack,会因构建时解析全部导入而警告:
Module not found: Error: Can't resolve 'sync-ammo'
此警告不影响未启用物理的应用。React 仅在 usePhysics 开启时加载,Vite 和 Turbopack 不会因此警告。
webpack 中可忽略该模块以消除警告:
webpack.config.js
const webpack = require('webpack');
module.exports = {
// ...
plugins: [
new webpack.IgnorePlugin({ resourceRegExp: /^sync-ammo$/ })
]
};
Next.js 可添加到 next.config.mjs,但仅限 next build --webpack;默认 Turbopack 遇到 webpack 配置会失败:
next.config.mjs
export default {
webpack: (config, { webpack }) => {
config.plugins.push(new webpack.IgnorePlugin({ resourceRegExp: /^sync-ammo$/ }));
return config;
}
};
注意
IgnorePlugin 即使已安装也阻止打包 sync-ammo,启用物理时应移除。