HTML5游戏引擎关卡切换本质是资源卸载+状态重置+新场景渲染;Phaser3用scene.start()最稳妥,Three.js需手动管理资源,Canvas2D宜用状态机,音频上下文须显式resume。

HTML5 游戏引擎本身不提供“页面跳转”式场景切换——它运行在单页应用(SPA)模型下,所谓“关卡切换”本质是资源卸载 + 状态重置 + 新场景渲染,不是 window.location.href 或路由跳转。
Phaser 3 中用 scene.start() 切换关卡最稳妥
Phaser 3 的 Scene 系统专为关卡管理设计,scene.start() 会自动暂停当前场景、初始化目标场景、触发其 init() → preload() → create() 生命周期。比手动销毁再新建更安全。
- 确保每个关卡都继承自
Phaser.Scene,并在config中注册唯一key - 避免在
create()里直接调用scene.start(),可能引发竞态;改用this.scene.scene.start()或延迟一帧:this.time.delayedCall(0, () => this.scene.start('Level2')) - 若需传参(如通关得分),用
scene.start('Level2', { score: 1200 }),目标场景的init(data)可接收data
Three.js 项目里别依赖浏览器路由做“关卡跳转”
Three.js 是渲染库,不是游戏引擎,没有内置场景管理。若强行用 history.pushState() 或 router.push() 切换 URL,只会刷新页面或破坏 WebGL 上下文——WebGLRenderingContext 一旦丢失,所有 BufferGeometry、Texture 都失效。
- 正确做法:用一个主
SceneManager类统一管理关卡实例,调用当前关卡的dispose()(手动释放几何体、材质、监听器),再实例化新关卡并挂载到同一renderer - 关键陷阱:
renderer.dispose()会清空整个上下文,不要调;只清理当前关卡持有的资源 - 若使用
OrbitControls,切换前必须调用controls.dispose(),否则事件监听器残留导致内存泄漏
Canvas 2D 游戏中用状态机替代“页面跳转”逻辑
纯 + requestAnimationFrame 实现的游戏,关卡切换就是状态变更:从 GAME_STATE.MENU → GAME_STATE.PLAYING → GAME_STATE.GAME_OVER。没有 DOM 页面概念,也无需加载新 HTML。
立即学习“前端免费学习笔记(深入)”;
- 把每关逻辑封装成独立对象(如
Level1类),含load()、update(dt)、render(ctx)、unload()方法 - 主循环中只调用当前关卡对象的
update()和render(),切换时先执行旧关卡unload(),再调新关卡load() - 切忌在
unload()里设ctx.clearRect()——那是渲染职责;清空的是定时器、事件监听、数组引用等
真正容易被忽略的点:音频上下文(AudioContext)在多数浏览器中不可跨“页面”恢复,即使你没刷新,只要用户切到其他标签页再回来,suspend() 状态就可能触发。关卡切换时得显式调用 audioContext.resume(),且最好在用户首次交互后才创建上下文。











