跳到主要内容

脚本加载顺序

ESM 脚本​

ESM 没有显式加载顺序,不应依赖特定先后,而应通过模块导入声明依赖。

经典脚本​

通常在应用启动前加载,顺序由项目设置决定,可从主菜单或场景设置访问:

加载顺序

面板列出标记为 preload 的经典脚本及加载执行顺序。

顺序列表

拖动脚本即可调整。

脚本首次加载后立即执行,因此顶层代码按加载顺序运行。但加载顺序不影响组件内脚本方法顺序。例如同一实体的 initialize 按实体脚本列表顺序调用。

预加载​

脚本与其他资源一样默认 preload。关闭后,通常不会自动加载,可保留在项目中但不启动。需要时通过常规资源 API 动态加载,见 AssetRegistry#load。

可以订阅脚本注册表的动态变化:

this.app.scripts.on('add', (name, scriptType) => {
console.log('script', name, 'has been loaded');
});

发布​

发布或下载 static 时,经典与 ESM 分别处理。Concatenate Scripts 和 Minify Scripts 控制处理程度,见发布新构建。输出文件见下载项目。

npm 下载格式不同,生成保留源码的 Vite 项目,因此下述处理和选项不适用。

经典脚本​

默认将所有预加载经典脚本拼接成单文件,减少请求并加快加载。

ESM 脚本​

ESM 项目作为 ES 模块应用构建,入口 js/index.mjs。默认启用 Concatenate Scripts,会将脚本与引擎打包:

  • 打包输出:引擎和启动代码进入 js/index.mjs,预加载 ESM 进入由其在启动时加载的共享模块。
  • Tree shaking:排除未使用引擎代码,但用户模块保持完整,因为项目中每个模块资源都要能按路径加载。
  • 代码分割:仅通过动态 import() 加载且关闭 Preload 的模块进入独立文件,首次调用时下载。预加载模块无论静态或动态引用,都进入共享模块。
  • 压缩:启用 Minify Scripts 后,压缩打包代码以减小体积。

代码分割适合延后菜单、可选工具和过场动画等内容。下例 cutscene.mjs 关闭 Preload,因此首次 play() 时才下载:

import { Script } from 'playcanvas';

export class Intro extends Script {
static scriptName = 'intro';

async play() {
const { Cutscene } = await import('./cutscene.mjs');
new Cutscene(this.app).play();
}
}

关闭 Concatenate Scripts 后,各 ESM 独立输出,引擎作为独立模块加载,不执行压缩。

混合 ESM 与经典脚本​

两者可共存,但分别处理:

  • ESM 按上文打包。
  • 经典脚本保持在 ESM 包外;启用拼接后,合并到自己的独立文件。
  • 经典脚本通过全局 pc 访问引擎,因此构建包含整个引擎,不进行引擎 tree shaking。
注意

不要在经典脚本中用 import() 加载 ESM。构建会移动 ESM 路径,只更新 ESM 内部的导入,因此编辑器可运行的调用发布后会失败。代码编辑器会为经典脚本中的 import() 警告。